Chris 2pha Brown

Chris Brown

Drupal, Javascript, Three.js, 3D

website blog

Experimenting with Three.js shaders and the ShaderMaterial

Lately when using Three.js I have needed some very specific material qualities that the built in Three.js materials did not allow for so I have started experimenting with the Three.ShaderMaterial. This material allows you to write you own GLSL shaders for Three.js. My hope is that I can get a good understanding of GLSL and implement some of my own shaders and materials in Three.js even with my limited math skills and no prior experience with GLSL.

On this page I will link to some of my own Three.ShaderMaterial experiments and try to update it as I learn more.

You may also want to take a look at my implementation of a three.js car paint shader (a recreartion of the Radeon 9700 demo).

NOTE: these examples are using R70 of THREE.js and material implementation seems to have changed a bit since the R70 release, so some of these may not work on the current release of THREE.js

Custom Mesh Shader Materials

On most of my experiments there are buttons under "Source" to view both the vertex shader source and the fragment shader source.

  • Basic color

    basic color shader
    This is the most basic of shaders, simple applying a color via the fragment shader.
  • Vertex position color

    Vertex position color shader
    Takes the fragment color from the vertex position. Simple experiment trying to understand how to send varyings from the vertex shader to the fragment shader
  • Uv position color

    Uv position color shader
    Takes the fragment color from the uv position. Again trying to understand how to send varyings from the vertex shader to the fragment shader
  • Normals

    Normal shader
    Displays the current fragment normal.
  • Checkerboard

    Checker board shader
    Getting a little more advanced here and actually doing some calculation and multiple uniforms.
  • Simple lines

    simple lines shader
    A simple lines shader in relation to this stackoverflow question
  • Faded lines

    faded lines shader
    Simple faded lines.
  • Dots

    dots shader
    Simple dots.
  • Noise (voronoise)

    "Voronoise" fragment shader
    In this shader I took a shader I found on shadertoy.com and implemented it as a Three.js ShaderMaterial.
  • Voronoi with borders

    Voronoi with borders shader
    This is also a moderfied shader found on shadertoy.com and implemented it as a Three.js ShaderMaterial.
  • Simplex noise 2d

    Simplex noise 2d
    Implementation of the 2d simplex noise function found here
  • Simplex noise 3d

    Simplex noise 3d
    Implementation of the 3d simplex noise function found here
  • Perlin noise 3d

    Perlin noise 3d
    Another noise, but Perlin this time.
  • Perlin noise 3d - vertex displacement

    Perlin noise 3d - vertex displacement
    Same as the Perlin example above except doing the noise calculation in the vertex shader and displacing each vertex.
  • Basic color with point lights

    Basic color with point lights
    This is the same as the first experiment with basic color, except this time adding some point lights. Notice the additional THREE.UniformsLib['lights'] uniforms added with THREE.UniformsUtils.merge() in the page source.
  • Voronoi with point lights = sparkle

    Voronoi with point lights
    Combine the voronoi with light intensity and you can get a simple sparkle effect.
  • Polkadot 3d Noise

    Polkadot noise
    An implementation of a polkadot type noise found here. The amount uniform does not work quite as expected, but it serves the purpose of a demo though. Also, setting the box uniform to 1 will give a squarish type effect.
  • Starburst

    Starburst
    A radial star burst type pattern.
  • 2 color fresnel

    2 color fresnel
    A 2 color fresnel type shader based on the code here. Instead of reflecting the environment, it adds another colour. Maybe such a shader could be used as a base in a two-tone/chameleon car paint shader.
  • Fresnel cubemap reflection

    fresnel cubemap reflection
    Same as above but reflecting a cubemap instead of a colour. This is pretty much just a copy of the Three.js fresnel example. It seems to have problems related to this issue about calculating the reflection vector in the vertex shader.
  • Fresnel cubemap reflection 2

    fresnel cubemap reflection
    Here is a copy of the above shader but with the reflection calculation moved to the fragment shader.
  • Wood grain

    wood grain
    A simple wood grain shader. From RenderMonkey
  • Cel / Toon shader with point lights

    cel shader
    A simple cel / toon shader with point lights. The intensity is taken from a uniform sent to the shader. It does not respect the light intensity or colour.
  • Cel / Toon shader with point lights 2

    cel shader 2
    Another cel shader this time there is no intensity uniform send to the shader. Instead, the intensity is taken from the point light colour (summed RGB values).
  • Matrix like shader

    matrix shader
    Matrix style shader borrowed from shadertoy.

Built-in uniforms and attributes

Three.js provides some uniforms and attributes to the vertex and fragment shaders of the ShaderMaterial by default as outlined at the WebGLProgram docs.

Vertex shader

  • uniform mat4 modelMatrix - object.matrixWorld
  • uniform mat4 modelViewMatrix - camera.matrixWorldInverse * object.matrixWorld
  • uniform mat4 projectionMatrix - camera.projectionMatrix
  • uniform mat4 viewMatrix - camera.matrixWorldInverse
  • uniform mat3 normalMatrix - inverse transpose of modelViewMatrix
  • uniform vec3 cameraPosition - camera position in world space
  • attribute vec3 position - vertex position
  • attribute vec3 normal - vertex normal
  • attribute vec2 uv -
  • attribute vec2 uv2 -

    Fragment shader

  • uniform mat4 viewMatrix - camera.matrixWorldInverse
  • uniform vec3 cameraPosition - camera position in world space

Articles and tutorials on creating shaders

Other articles not directly related to Three.js, webGL or shaders, but are interesting anyway.