Skip to content

Add WebGL.Texture.loadBytesWith #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@
"F4": false,
"F5": false,
"F6": false,
"F9": false,
"A2": false,
"A5": false,
"Float32Array": false,
"Int32Array": false,
"Uint16Array": false
"Uint16Array": false,
"Uint8Array": false
}
}
1 change: 1 addition & 0 deletions elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
],
"elm-version": "0.19.0 <= v < 0.20.0",
"dependencies": {
"elm/bytes": "1.0.8 <= v < 2.0.0",
"elm/core": "1.0.0 <= v < 2.0.0",
"elm/html": "1.0.0 <= v < 2.0.0"
},
Expand Down
28 changes: 28 additions & 0 deletions src/Elm/Kernel/Texture.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,31 @@ var _Texture_load = F6(function (magnify, mininify, horizontalWrap, verticalWrap
var _Texture_size = function (texture) {
return __Utils_Tuple2(texture.__width, texture.__height);
};


//Texture Loading from Bytes

// eslint-disable-next-line no-unused-vars
var _Texture_loadBytes = F9(function (magnify, mininify, horizontalWrap, verticalWrap, flipY, width, height, pixelFormat, bytes) {
function createTexture(gl) {
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
gl.texImage2D(gl.TEXTURE_2D, 0, pixelFormat, width, height, 0, pixelFormat, gl.UNSIGNED_BYTE, new Uint8Array(bytes.buffer));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magnify);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, mininify);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, horizontalWrap);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, verticalWrap);
if (mininify !== 9728 && mininify !== 9729) {
gl.generateMipmap(gl.TEXTURE_2D);
}
gl.bindTexture(gl.TEXTURE_2D, null);
return texture;
}
return {
$: __0_TEXTURE,
__$createTexture: createTexture,
__width: width,
__height: height
};
});
116 changes: 114 additions & 2 deletions src/WebGL/Texture.elm
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ module WebGL.Texture
, nonPowerOfTwoOptions
, repeat
, size
, Format
, loadBytesWith
, unsafeLoad
, rgb , rgba, luminanceAlpha, luminance, alpha
)

{-|
Expand Down Expand Up @@ -51,10 +55,11 @@ module WebGL.Texture

# Things You Shouldn’t Do

@docs nonPowerOfTwoOptions
@docs nonPowerOfTwoOptions, loadBytesWith, unsafeLoad, Format, rgb , rgba, luminanceAlpha, luminance, alpha

-}

import Bitwise
import Bytes exposing (Bytes)
import Elm.Kernel.Texture
import Task exposing (Task)

Expand Down Expand Up @@ -304,3 +309,110 @@ or other times you may want to use only a potion of a texture image.
size : Texture -> ( Int, Int )
size =
Elm.Kernel.Texture.size



{-| Building [`Texture`](#Texture) from bytes

- [`Options`](#Options) - same as for [`loadWith`](#loadWith)

- `(width, height)` - dimensions of new created texture

- [`Format`](#Format) - pixel format in bytes

- Bytes - encoded pixels, where `Bytes.width` > `width` \* `height` \* `Bytes per pixe`or you get `SizeError`

Do not generate texture in `view`, [read more about this here](https://package.elm-lang.org/packages/elm-explorations/webgl/latest#making-the-most-of-the-gpu).

-}
loadBytesWith :
Options
-> ( Int, Int )
-> Format
-> Bytes
-> Result Error Texture
loadBytesWith ({ magnify, minify, horizontalWrap, verticalWrap, flipY } as opt) ( w, h ) ((Format _ bytesPerPixel) as format) b =
let
isMipmap =
minify /= nearest && minify /= linear

widthPowerOfTwo =
Bitwise.and (w - 1) w == 0

heightPowerOfTwo =
Bitwise.and (h - 1) h == 0

isSizeValid =
(widthPowerOfTwo && heightPowerOfTwo) || (not isMipmap && horizontalWrap == clampToEdge && verticalWrap == clampToEdge)
in
if w > 0 && h > 0 && isSizeValid && Bytes.width b >= w * h * bytesPerPixel then
Ok (unsafeLoad opt ( w, h ) format b)

else
Err (SizeError w h)


{-| It is intended specifically for library writers who want to create custom texture loaders.
-}
unsafeLoad :
Options
-> ( Int, Int )
-> Format
-> Bytes
-> Texture
unsafeLoad { magnify, minify, horizontalWrap, verticalWrap, flipY } ( w, h ) (Format format _) b =
let
expand (Resize mag) (Resize min) (Wrap hor) (Wrap vert) =
Elm.Kernel.Texture.loadBytes mag min hor vert flipY w h format b
in
expand magnify minify horizontalWrap verticalWrap

{-| How to read bytes intpo pixel

| Format | Channels | Bytes per pixel |
------------------------------------------------
| rgba | 4 | 4 |
| rgb | 3 | 3 |
| luminanceAlpha | 2 | 2 |
| luminance | 1 | 1 |
| alpha | 1 | 1 |
------------------------------------------------

-}
type Format
= Format Int Int


{-| Single pixel is 4 bytes long and have 4 channels
-}
rgba : Format
rgba =
Format 6408 4


{-| Single pixel is 3 bytes long and have 3 channels
-}
rgb : Format
rgb =
Format 6407 3


{-| Single pixel is 2 bytes long and have 2 channels
-}
luminanceAlpha : Format
luminanceAlpha =
Format 6410 2


{-| Single pixel is 1 bytes long and have 1 channels
-}
luminance : Format
luminance =
Format 6409 1


{-| Single pixel is 1 bytes long and have 1 channels
-}
alpha : Format
alpha =
Format 6406 1