WebGL is one of the main reasons why I start learning elm at all. After 2.5y of investigation found that elm is the easiest way to do some crazy experiments. But also found that there is a lack of main functionality that is provided by WebGL, especially in textures, and 2D filters (Yes WebGL is not only about 3D).
Images are great - but that is not the only way Textures can be used for, but Elm implementation is limited to only that, and most worse part of that - you cannot get Texture
without Task
(that is due to JavaScript limitation of loading image in an async way, even from base64
encode url).
So I started the investigation, how at all WebGL works in elmā¦ and found that hacking on elm-exploration
stuff is only for āchosen oneā - as the development process is kept as The Secret, no manuals, no documentation, no comments in code, code is formatted in a weird way, no generic tools used to format elm or js code.
But after some tweaks/hacks/manipulations I finally got it working (feed in my changes of native code to elm). But letās keep that as The Secret.
Back to Textures - they (textures) can be used not just as images, but also as 2d arrays with some data (each pixel is just 32bit - where you can encode any data)
Would be nice to have access to that, and be able to compose Texture
in elm, that would give to advanced developer more freedom, and beginners more gradual steps to evolve (not think about Task
, and require upgrade Browser.sandbox
to Browser.element
).
Now We have:
WebGL.Texture.loadWith : Options -> String -> Task Error Texture
I was able to create new function to creating texture:
WebGL.Texture.fromList: Options -> Width -> List Pixels -> Texture
*Pixel
is Int
in format 0xRRGGBBAA
Use cases:
- You can create texture without
Task
, and use it as the fallback or initial value for textures, so no need to create different models when a texture is loaded and when not. - Texture can store permanent data - cracks on walls, bullet holes, dead bodies - something that updates rarely, but need be passed to the GPU somehow
- Randomness in shaders - can generate noise texture, and use that in the shader, instead of calculating noise values each frame per each pixel
- Generate Look Up Tables - for tile-based games ( More details about this rendering technique can be found in Brandon Jonesā blog.)
- Testing - texture can be create as mock in
Model
(to test states with loaded textures) - Custom image or/and scene loaders - the community will be able to create custom format parsers that can be loaded in WebGL (images: TGA, DDS, BMfontā¦ scene: gltf, BSP)
- Any shader that requires a lot of data and data can be obtained only during runtime.
Problem with my current solution - is that it hides some stuff underhood:
-
List Pixel
can be any length, but the image must be rectangular - so it automatically adds empty pixels (rgba(0,0,0,0)
) - if a texture is non-power-of-two (NPOT) (and in my opinion that is most of the cases with generated textures) you cannot generate mipmaps, so
WebGL.Texture.fromList
will silently overwrite those options. -
List
on Js side is quite not so pleasant to work with, so it requires to loop over all ints, to pass it to the texture binding.
So I see a few solutions to that:
-
WebGL.Texture.fromList: Options -> Width -> List Pixels -> Result Error Texture
whereError
is justSizeError
orTexture
- Leave as is - and explain all fallback cases in documentation
- Have two versions:
3.1WebGL.Texture.fromList: Options -> Width -> Height -> List Pixels -> Result Error Texture
3.2WebGL.Texture.unsafaFromList: Options -> Width -> List Pixels -> Texture
Any API / suggestion / objection / questions are welcomeā¦ (code will fallow as pull request when will find the best solution - hope you will help)