Shadertoy for Elm
Elm JavaScript HTML
Latest commit 051d819 Apr 19, 2017 @kfish Update for Elm 0.18
Failed to load latest commit information.
resources Update for Elm-0.17 as elm-first-person (crates) Jun 21, 2016
src Update for Elm 0.18 Apr 19, 2017
.gitignore Initial check in May 24, 2014
LICENSE Initial check in May 24, 2014 Update for Elm 0.18 Apr 19, 2017

Shadertoy for Elm

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.

How it works

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:

Live Demo

Importing Shadertoy fragment shaders

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;




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.

What is NOT (YET) supported

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):

  1. Support Shadertoy channel inputs
  2. Support Shadertoy mouse input
  3. Support Shadertoy date input

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).

Build Locally

After installing the Elm Platform, run the following sequence of commands:

git clone
cd elm-shadertoy
elm-package install
elm-make src/Main.elm --output build/Main.js

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: