Skip to content

Commit ea4f2c4

Browse files
committed
Add WebGL.Texture.loadBytesWith
1 parent a0d420a commit ea4f2c4

File tree

3 files changed

+123
-2
lines changed

3 files changed

+123
-2
lines changed

elm.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
],
1515
"elm-version": "0.19.0 <= v < 0.20.0",
1616
"dependencies": {
17+
"elm/bytes": "1.0.8 <= v < 2.0.0",
1718
"elm/core": "1.0.0 <= v < 2.0.0",
1819
"elm/html": "1.0.0 <= v < 2.0.0"
1920
},

src/Elm/Kernel/Texture.js

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
33
import Elm.Kernel.Utils exposing (Tuple2)
44
import Elm.Kernel.Scheduler exposing (binding, succeed, fail)
5-
import WebGL.Texture as Texture exposing (LoadError, SizeError)
5+
import WebGL.Texture as Texture exposing (LoadError, SizeError, RGBA, RGB, LUMINANCE_ALPHA, LUMINANCE, ALPHA)
6+
import Result exposing (Err, Ok)
67
78
*/
89

@@ -65,3 +66,72 @@ var _Texture_load = F6(function (magnify, mininify, horizontalWrap, verticalWrap
6566
var _Texture_size = function (texture) {
6667
return __Utils_Tuple2(texture.__width, texture.__height);
6768
};
69+
70+
71+
//Texture Loading from Bytes
72+
73+
74+
function getFormat(gl, format) {
75+
return (format == __Texture_RGBA && gl.RGBA)
76+
|| (format == __Texture_RGB && gl.RGB)
77+
|| (format == __Texture_LUMINANCE_ALPHA && gl.LUMINANCE_ALPHA)
78+
|| (format == __Texture_LUMINANCE && gl.LUMINANCE)
79+
|| (format == __Texture_ALPHA && gl.ALPHA)
80+
}
81+
82+
function getByteCount(format) {
83+
return (format == __Texture_RGBA && 4)
84+
|| (format == __Texture_RGB && 3)
85+
|| (format == __Texture_LUMINANCE_ALPHA && 2)
86+
|| (format == __Texture_LUMINANCE && 1)
87+
|| (format == __Texture_ALPHA && 1)
88+
}
89+
90+
// eslint-disable-next-line no-unused-vars
91+
var _Texture_loadBytes = F9(function (magnify, mininify, horizontalWrap, verticalWrap, flipY, width, height, format, bytes) {
92+
var isMipmap = mininify !== 9728 && mininify !== 9729;
93+
function createTexture(gl) {
94+
var pixelFormat = getFormat(gl, format);
95+
var texture = gl.createTexture();
96+
gl.bindTexture(gl.TEXTURE_2D, texture);
97+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
98+
gl.texImage2D(gl.TEXTURE_2D, 0, pixelFormat, width, height, 0, pixelFormat, gl.UNSIGNED_BYTE, new Uint8Array(bytes.buffer));
99+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magnify);
100+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, mininify);
101+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, horizontalWrap);
102+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, verticalWrap);
103+
if (isMipmap) {
104+
gl.generateMipmap(gl.TEXTURE_2D);
105+
}
106+
gl.bindTexture(gl.TEXTURE_2D, null);
107+
return texture;
108+
}
109+
if (bytes.byteLength < width * height * getByteCount(format)) {
110+
return __Result_Err(A2(
111+
__Texture_SizeError,
112+
width,
113+
height
114+
));
115+
}
116+
var widthPowerOfTwo = (width & (width - 1)) === 0;
117+
var heightPowerOfTwo = (height & (height - 1)) === 0;
118+
var isSizeValid = (widthPowerOfTwo && heightPowerOfTwo) || (
119+
!isMipmap
120+
&& horizontalWrap === 33071 // clamp to edge
121+
&& verticalWrap === 33071
122+
);
123+
if (isSizeValid) {
124+
return __Result_Ok({
125+
$: __0_TEXTURE,
126+
__$createTexture: createTexture,
127+
__width: width,
128+
__height: height
129+
});
130+
} else {
131+
return __Result_Err(A2(
132+
__Texture_SizeError,
133+
width,
134+
height
135+
));
136+
}
137+
});

src/WebGL/Texture.elm

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ module WebGL.Texture
2121
, nonPowerOfTwoOptions
2222
, repeat
2323
, size
24+
, Format(..)
25+
, loadBytesWith
2426
)
2527

2628
{-|
@@ -51,10 +53,11 @@ module WebGL.Texture
5153
5254
# Things You Shouldn’t Do
5355
54-
@docs nonPowerOfTwoOptions
56+
@docs nonPowerOfTwoOptions, loadBytesWith, Format
5557
5658
-}
5759

60+
import Bytes exposing (Bytes)
5861
import Elm.Kernel.Texture
5962
import Task exposing (Task)
6063

@@ -304,3 +307,50 @@ or other times you may want to use only a potion of a texture image.
304307
size : Texture -> ( Int, Int )
305308
size =
306309
Elm.Kernel.Texture.size
310+
311+
312+
{-| Building [`Texture`](#Texture) from bytes
313+
314+
- [`Options`](#Options) - same as for [`loadWith`](#loadWith)
315+
316+
- `(width, height)` - dimensions of new created texture
317+
318+
- [`Format`](#Format) - pixel format in bytes
319+
320+
- Bytes - encoded pixels, where `Bytes.width` > `width` \* `height` \* `Bytes per pixe`or you get `SizeError`
321+
322+
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).
323+
324+
-}
325+
loadBytesWith :
326+
Options
327+
-> ( Int, Int )
328+
-> Format
329+
-> Bytes
330+
-> Result Error Texture
331+
loadBytesWith { magnify, minify, horizontalWrap, verticalWrap, flipY } ( w, h ) format b =
332+
let
333+
expand (Resize mag) (Resize min) (Wrap hor) (Wrap vert) =
334+
Elm.Kernel.Texture.loadBytes mag min hor vert flipY w h format b
335+
in
336+
expand magnify minify horizontalWrap verticalWrap
337+
338+
339+
{-| How to read bytes intpo pixel
340+
341+
| Format | Channels | Bytes per pixel |
342+
------------------------------------------------
343+
| RGBA | 4 | 4 |
344+
| RGB | 3 | 3 |
345+
| LUMINANCE_ALPHA | 2 | 2 |
346+
| LUMINANCE | 1 | 1 |
347+
| ALPHA | 1 | 1 |
348+
------------------------------------------------
349+
350+
-}
351+
type Format
352+
= RGBA
353+
| RGB
354+
| LUMINANCE_ALPHA
355+
| LUMINANCE
356+
| ALPHA

0 commit comments

Comments
 (0)