Analytical Surfaces Evaluated by the GPU Texture Sampler

This is a demo to go along with my blog post: Evaluating Points on Analytical Surfaces and in Analytical Volumes Using the GPU Texture Sampler

This page uses WebGL2, which will be enabled by default in chrome 56 in January 2017.
To enable WebGL2 before then, or on other browsers, see this link: How to use WebGL2

Drag the mouse to rotate the surface.


Degree:
Shading Mode:
Draw Bounding Box:
Draw Control Points:
Draw Isolines:

Control Points:
Row 0
 00:
 10:
Row 1
 01:
 11:
Row 0
 00:
 10:
 20:
Row 1
 01:
 11:
 21:
Row 0
 00:
 10:
 20:
Row 1
 01:
 11:
 21:
Row 2
 02:
 12:
 22:
Row 0
 00:
 10:
 20:
 30:
Row 1
 01:
 11:
 21:
 31:
Row 2
 02:
 12:
 22:
 32:
Row 3
 03:
 13:
 23:
 33:

How It's Rendered

The rendering is done by doing a ray trace of the bounding cube to see which rays might intersect the surface.

The rays that hit the cube then ray march from the start of the cube to the end of the cube to see if they hit the surface. If they do hit the surface, they are shaded, else they are not.

Instead of doing the initial ray trace, the cube could be rendered with triangles so that it would become a rasterization process instead of a full screen raytrace vs a box. The ray marching would still be done in the pixel shader like it is now. The ray marching could be improved by using the gradient to take varying sized steps instead of constant sized steps.

There is some non smoothness of the normals (seen best in the specular highlight) and the surface positions that is due to the fact that the texture interpolator works in X.8 fixed point numbers. You can verify this by using the software interpolated dreeg selection to see it smooth out.

The GPU texture sampler is used to calculate the y axis value (height) of the surface at a given u,v (or x,z) position, as described below.

Bilinear

The four control points are stored in a 2x2 2d texture's R channel in this pattern:

0010
0111


For a u,v coordinate, the texture is sampled at (uv + 0.5) / 2.0, with the R component of the result having the surface height.

Bilinear (Software Interpolation)

The texture is the same as above, but the pixel shader samples the texture at (0.25, 0.25), (0.75, 0.25), (0.25, 0.75), (0.75, 0.75) to get the control points, and then does bilinear interpolation manually using three mix operations.

Quadratic / Linear

The 6 control points are stored in a 2x2x2 3d volume texture's R channel in this pattern:

Slice 0
0010
1020
Slice 1
0111
1121


For a u,v coordinate, the texture is sampled at (uv.xxy + 0.5) / 2.0, with the R component of the result having the surface height.

Biquadratic

The 9 control points are stored in a 2x2 2d texture's RGB channels. Each color channel contains a quadratic curve across the u axis like below:

Red
0010
1020
Green
0111
1121
Blue
0212
1222


For a u,v coordinate, the texture is sampled at (uv.xx + 0.5) / 2.0 to get 3 quadratic curves in R,G,B. The R,G,B results are then combined with the quadratic Bezier equation using uv.y to get the surface height.

Bicubic

The 16 control points are stored in a 2x2x2 3d volume texture's RGBA channels. Each color channel contains a cubic curve across the u axis like below:

Red Layer 0
0010
1020
Green Layer 0
0111
1121
Blue Layer 0
0212
1222
Alpha Layer 0
0313
1323
Red Layer 1
1020
2030
Green Layer 1
1121
2131
Blue Layer 1
1222
2232
Alpha Layer 1
1323
2333


For a u,v coordinate, the texture is sampled at (uv.xxx + 0.5) / 2.0 to get 4 cubic curves across u in R,G,B,A. The R,G,B,A results are then combined with the cubic Bezier equation using uv.y to get the surface height.