Procedural Shaders

This is some fun stuff I did around July in my free time, and was re-organized and cleaned up a bit recently.

Check out the demo in your brower. Having a problem open WebGL demo? Try here.
Source code on Github

There’re three models – cube, sphere, torus knot and three shaders – wood, marble, lava to choose from, and a check box to toggle visualizer for the directional light.

Here we go!

At first sight, you must be thinking “Hmm…this looks familiar…did I just open Maya?” :P That’s because I use a similar linear gradient background color as in Maya, with help from this super convenient online gradient editor.

Let’s get to the subject…shaders! I’m gonna skip all the setups in html file. There’re tons of WebGL tutorials available, I’m pretty sure they explain better than I do…

 Wood with half lambert diffuse:wood

THREE.ShaderChunk["simplex_noise"]  refers to the simplex noise implementation by Ashima Arts. There was lots of trial and error on my way to find the wood pattern, as well as marble and lava. After all, I get to a conclusion that a 100% perfect formula for this doesn’t exist yet. The result someone else got, may end in “OMG I don’t know what that thing is” when used in your situation. The multipliers and offsets depend a lot on the size of your model – I mean the position of vertices. Hugo Elias’s page about Perlin noise particularly helped me get the desired result.
Half lambert is a lighting technique developed by Valve in the original Half-Life, to prevent the rear of an object losing its shape and looking too flat.

Marble with ambient, lambert diffuse and blinn phong specular:marble

In order to generate the marble pattern, we need a turbulence function. I wrote one based on Perlin Noise and Turbulence by Paul Bourke, put it in  THREE.ShaderChunk["turbulence"] :

Blinn Phong can cause artifact when used with a relatively small specular power, so I used a value of 50. The details are clearly explained here. If you don’t wanna know about details it’s ok…we’re going to the era of physically based shading, aren’t we? :P

Lava with vertex displacement and emissive:
You didn’t see anything in the first picture…
You didn’t see anything in the first picture…
You didn’t see anything in the first picture…

Oh well, you see it, it’s broken! It’s because of the way cube geometry is implemented in WebGL(and other GL as well). The cube is often defined with 24 vertices, having vertex normals perpendicular to each face. Vertices on the edges share the position however have different normals. This prevents the normal making a 135 degree angle to adjacent faces thus resulting a weird looking sphere after shading.

This lava shader is the most intensive of the above three, because it uses noise function to get vertex displacement in the vertex shader, besides utilizing turbulence to generate texture in the pixel shader. These two demos fireball, explosion gave me inspiration to come up with the lava pattern and behavior that fit my scene.

I’d say this is fun! I got to know WebGL in May, via Udacity’s amazing course on computer graphics. It’s really an easy way to prototype ideas without much iteration time, and get fascinating things rendering in your browser. Although the Three.js library changes fast, and we have to adapt to that, it’s a good way to practice and learn from others.

Leave a Reply