Shadertoy is a community of shader developers, sharing code with online demos.
Elm is a very concise language with Web GL support.
The purpose of this project is to make it easy to incorporate shaders from Shadertoy in Elm projects.
The significance is that the work of these two outstanding developer communities can be multiplied: Elm developers can learn advanced shader techniques, and shader developers can easily build larger interactive systems.
You can define vertex meshes, game logic and physics very clearly in Elm, then write your shaders directly in GLSL. The Elm compiler translates the Elm code to Javascript and checks the GLSL for parse errors. On the client web browser, the GLSL is interpreted by the system OpenGL system, such as the GPU driver.
Make sure you have the latest version of Chrome or Firefox and then click the following image to try out the live demo:
Shaders in Elm are included verbatim in a [glsl| ... ]
block.
Use the following types and preamble to define a fragment shader named foo
:
foo : Shader {} { u | iResolution:Vec3, iGlobalTime:Float } { elm_FragCoord:Vec2 }
foo = [glsl|
precision mediump float;
uniform vec3 iResolution;
uniform float iGlobalTime;
varying vec2 elm_FragCoord;
<<<SHADER CODE GOES HERE>>>
|]
Shadertoy defines various inputs to fragment shaders. elm-shadertoy provides compatibility for the following:
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform float iGlobalTime; // shader playback time in seconds
elm-shadertoy additionally defines 'elm_FragCoord'.
varying vec2 elm_FragCoord; // texture-space fragment coordinate
Replace all occurrences of gl_FragCoord.xy / iResolution.xy
with elm_FragCoord.xy
. This
ensures that pixels are calculated according to their location on 3D surface, rather than
their location on your 2D screen.
The following Shadertoy inputs are not yet supported by elm-shadertoy:
uniform float iChannelTime[4]; // channel playback time (in seconds)
uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click
uniform samplerXX iChannel0..3; // input channel. XX=2D/Cube
uniform vec4 iDate; // (year, month, day, time in seconds)
These are tracked in issues in this project (elm-shadertoy):
Additionally, there is an issue in the Haskell language-glsl package regarding the GLSL preprocessor: support for #define, #ifdef etc., so you need to manually preprocess (replace constants by variables, use comments to select behavior instead of #ifdef).
After installing the Elm Platform, run the following sequence of commands:
git clone https://github.com/kfish/elm-shadertoy.git
cd elm-shadertoy
elm-package install
elm-make src/Main.elm --output build/Main.js
elm-reactor
And then open http://localhost:8000 to see it in action!
The Elm code here is forked from Evan Czaplicki's first-person-elm demo. The update for Elm-0.17 is based on Günther Enthaler's fork.
Although the broader purpose of this project is to make it easy to use any shader from Shadertoy, this demo in particular includes the following shaders:
- Fire by 301
- Fog Mountains by ESpitz
- Simple Plasma by Kastor
- Voronoi distances by iq