Ddoodm's WebGL & GLSL ES Demos

My first (decent) raymarched distance field!
The geometry in the scene is described as a "Distance Function", which returns the nearest distance to the scene from any arbitrary 3D point; that means we need to think about the geometry in terms of its distance from $P$, which really bends me head.

Your browser doesn't seem to support HTML5 <canvas>.

fTime: 0.00

Neat Features

Raymarching Overview

We cast a 'ray' out from each fragment, and iterate a point along the ray $t \times |\vec r_d|$ by adding the distance to the scene: $d + t$, for an arbitrary number of iterations (100 iterations of a for loop in this case). $\vec r_d$ is the ray direction vector, and $t$ is the distance along the ray.

Once we have reached some minimum threshold of $d$ (the distance to the scene from the point on the ray), the point on the ray is so close to the scene that we can assume that the point is very near to the geometry.

Alternatively, if $t$ is so large that we are sure it is outside the scene, we can break the raymarcher loop, and perform some other type of colour compution; perhaps a 'sky' environment.

From there, we can do all sorts of linear algebra magic to move the 'camera' and create the 'purdy colours' you see on your display.

Camera Coordinate System

We wish to construct a "look-at" reference frame in order to find the direction at which to fire the ray. To construct a 3D Cartesian reference frame, we need 3 vectors that are perpendicular to each other: $w$ (the direction), $u$ (the vector orthonormal to $w$ and an arbitrary $up$ vector), and $v$ (the vector orthonormal to $w$ and $u$).

$$ up = 0x + 1y + 0z $$ $$ w = | target - ro | $$ $$ u = | w \times up | $$ $$ v = | u \times w | $$ Reference Frame

We can express our coordinate system as a generic transform by packing it into a 3D matrix: $$ M = \left[ \begin{matrix} u_x & u_y & u_z \\ v_x & v_y & v_z \\ w_x & w_y & w_z \\ \end{matrix} \right] $$ Finally, we obtain the new ray direction by multiplying it with our coordinate system. $$ rd' = | M \times rd| $$ $$ = | rd_xu + rd_yv + rd_zw | $$

Lighting

The lighting you're seeing here is no more than the application of Lambert's Law and some Phong specular reflectance.

The 'sky' colour is computed as such, where $\vec C$ is the final fragment colour, $\vec c_a$ & $\vec c_b$ are arbitrary RGB colours, $\vec r_d$ is the ray direction, and $\vec L$ is the light direction vector: $$ \vec C = \vec c_a \times \vec r_d \cdot \vec L + \vec c_b \times \vec r_d \cdot -\vec L $$ We obtain the surface normal at any collision point by obtaining the difference between two points a small distance around the collision.

Fragment Shader Source

The entire render is drawn onto no more than two triangles (a quad), shaded with the following GLSL Fragment Shader code. I've tried to comment the code reasonably well for your learning pleasure!

© Deinyon Davies 2014
Math notation powered by MathJax ®