Here is a neat example of using shaders in WebGL, read on to see the GLSL shader code
Fragment Shader
This is an example of Ray Marching using Distance Fields. The map
function given
here is for a sphere, it accepts a point p
and returns the distance p
is from
the surface of a sphere with radius 0.25
units.
By first manipulating p
by calling fract(p)
on it (basically mod 1), we get
multiple equally spaced spheres. length()
performs the 3D pythagorean theorem
in order to see how far away p
is.
The trace()
function receives the origin o
and the ray r
, and casts the ray
outwards towards the object in the map()
function by multiplying it by t
.
This makes the trace()
function search for the surface of an object iteratively,
here over a maximum of 32 iterations. Each iteration it projects the ray half the
distance remaining returned by the distance function, which zooms in safely until it finds
the shape’s boundary.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
The screen here is really a quad the same size as the viewport, so each fragment has a uv coordinate on that quad.
Next we expand the 2D uv coordinate into 3D called r
for ray, and normalize it to unit length, and establish an origin.
together these make a ray that is cast through that point on the screen. I adjust the z-coorindate
by multiplying it by time
which makes us seem to zoom through the scene.
The next thing I do is create a 2D rotation matrix, which I multiply by the ray’s xy
vector, the
angle of rotation theta
is also adjusted over time.
Now I use trace
to calculate the distance a ray travels into the scene before hitting something. The
value fog
is trying to use an inverse square equation to make more distant points seem darker than nearby points.
Finally fog
is used to compose an RGB color, mostly purple, but also modified by time to slowly change
the color of the spheres. Finally the fragment color is returned.
Vertex Shader
1 2 3 4 5 6 7 |
|
Not much happening in the vertex shader, we apply the model and projection matrices, most importantly
we pass the time
and resolution
uniforms we receive from javascript along to the fragment shader.