Skip to content

Commit b457ccc

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

File tree

3 files changed

+131
-27
lines changed

3 files changed

+131
-27
lines changed

elm.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "elm-explorations/webgl",
44
"summary": "Functional rendering with WebGL in Elm",
55
"license": "BSD-3-Clause",
6-
"version": "1.1.0",
6+
"version": "1.2.0",
77
"exposed-modules": [
88
"WebGL",
99
"WebGL.Settings",
@@ -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: 70 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,71 @@ 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+
// eslint-disable-next-line no-unused-vars
90+
var _Texture_loadBytes = F9(function (magnify, mininify, horizontalWrap, verticalWrap, flipY, width, height, format, bytes) {
91+
var isMipmap = mininify !== 9728 && mininify !== 9729;
92+
function createTexture(gl) {
93+
var pixelFormat = getFormat(gl, format);
94+
var texture = gl.createTexture();
95+
gl.bindTexture(gl.TEXTURE_2D, texture);
96+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
97+
gl.texImage2D(gl.TEXTURE_2D, 0, pixelFormat, width, height, 0, pixelFormat, gl.UNSIGNED_BYTE, new Uint8Array(bytes.buffer));
98+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magnify);
99+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, mininify);
100+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, horizontalWrap);
101+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, verticalWrap);
102+
if (isMipmap) {
103+
gl.generateMipmap(gl.TEXTURE_2D);
104+
}
105+
gl.bindTexture(gl.TEXTURE_2D, null);
106+
return texture;
107+
}
108+
if (bytes.byteLength < width * height * getByteCount(format)) {
109+
return __Result_Err(A2(
110+
__Texture_SizeError,
111+
width,
112+
height
113+
));
114+
}
115+
var widthPowerOfTwo = (width & (width - 1)) === 0;
116+
var heightPowerOfTwo = (height & (height - 1)) === 0;
117+
var isSizeValid = (widthPowerOfTwo && heightPowerOfTwo) || (
118+
!isMipmap
119+
&& horizontalWrap === 33071 // clamp to edge
120+
&& verticalWrap === 33071
121+
);
122+
if (isSizeValid) {
123+
return __Result_Ok({
124+
$: __0_TEXTURE,
125+
__$createTexture: createTexture,
126+
__width: width,
127+
__height: height
128+
});
129+
} else {
130+
return __Result_Err(A2(
131+
__Texture_SizeError,
132+
width,
133+
height
134+
));
135+
}
136+
});

src/WebGL/Texture.elm

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,13 @@
1-
module WebGL.Texture
2-
exposing
3-
( Bigger
4-
, Error(..)
5-
, Options
6-
, Resize
7-
, Smaller
8-
, Texture
9-
, Wrap
10-
, clampToEdge
11-
, defaultOptions
12-
, linear
13-
, linearMipmapLinear
14-
, linearMipmapNearest
15-
, load
16-
, loadWith
17-
, mirroredRepeat
18-
, nearest
19-
, nearestMipmapLinear
20-
, nearestMipmapNearest
21-
, nonPowerOfTwoOptions
22-
, repeat
23-
, size
24-
)
1+
module WebGL.Texture exposing
2+
( Texture, load, Error(..), size
3+
, loadWith, Options, defaultOptions
4+
, Resize, linear, nearest
5+
, nearestMipmapLinear, nearestMipmapNearest
6+
, linearMipmapNearest, linearMipmapLinear
7+
, Bigger, Smaller
8+
, Wrap, repeat, clampToEdge, mirroredRepeat
9+
, nonPowerOfTwoOptions, loadBytesWith, Format(..)
10+
)
2511

2612
{-|
2713
@@ -51,10 +37,11 @@ module WebGL.Texture
5137
5238
# Things You Shouldn’t Do
5339
54-
@docs nonPowerOfTwoOptions
40+
@docs nonPowerOfTwoOptions, loadBytesWith, Format
5541
5642
-}
5743

44+
import Bytes exposing (Bytes)
5845
import Elm.Kernel.Texture
5946
import Task exposing (Task)
6047

@@ -304,3 +291,50 @@ or other times you may want to use only a potion of a texture image.
304291
size : Texture -> ( Int, Int )
305292
size =
306293
Elm.Kernel.Texture.size
294+
295+
296+
{-| Building [`Texture`](#Texture) from bytes
297+
298+
- [`Options`](#Options) - same as for [`loadWith`](#loadWith)
299+
300+
- `(width, height)` - dimensions of new created texture
301+
302+
- [`Format`](#Format) - pixel format in bytes
303+
304+
- Bytes - encoded pixels, where `Bytes.width` > `width` \* `height` \* `Bytes per pixe`or you get `SizeError`
305+
306+
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).
307+
308+
-}
309+
loadBytesWith :
310+
Options
311+
-> ( Int, Int )
312+
-> Format
313+
-> Bytes
314+
-> Result Error Texture
315+
loadBytesWith { magnify, minify, horizontalWrap, verticalWrap, flipY } ( w, h ) format b =
316+
let
317+
expand (Resize mag) (Resize min) (Wrap hor) (Wrap vert) =
318+
Elm.Kernel.Texture.loadBytes mag min hor vert flipY w h format b
319+
in
320+
expand magnify minify horizontalWrap verticalWrap
321+
322+
323+
{-| How to read bytes intpo pixel
324+
325+
| Format | Channels | Bytes per pixel |
326+
------------------------------------------------
327+
| RGBA | 4 | 4 |
328+
| RGB | 3 | 3 |
329+
| LUMINANCE_ALPHA | 2 | 2 |
330+
| LUMINANCE | 1 | 1 |
331+
| ALPHA | 1 | 1 |
332+
------------------------------------------------
333+
334+
-}
335+
type Format
336+
= RGBA
337+
| RGB
338+
| LUMINANCE_ALPHA
339+
| LUMINANCE
340+
| ALPHA

0 commit comments

Comments
 (0)