Creative Tinkering


Go to Fullscreen

Despite Its 3D focus WebGL is actually a 2D graphics API. The 3D-ness of the graphics comes from complex transformations creating an illusion of 3D space on a 2D screen like a painting on a canvas.

There are plenty of 2D applications for WebGL as well. Some interesting and complex visuals can be achieved using the awesome speed that GPU processing provides. Although polygon modeled graphics has the most practicality even in 2D applications there are some “meshless” alternatives.

In this case I am experimenting with a method called distance field. The logic of distance field graphics lies in the distance function. Shapes do not have a sharp border (it can be argued even that there is no such thing as a shape). The border is derived by an arbitrary threshold value or in case of a signed distance field the negative values are considered as “inside”.

The distance function in the core of it all is a function that calculates a distance value from an input coordinate be it in 1D, 2D, 3D or even ND. This is purely a mathematical expression so it is very easy to create abstract and non-newtonian shapes. Interesting effects can also be achieved by manipulating the input coordinates. So at every point on the screen we must evaluate a distance value. It can be hard to visualize this at first but a few examples should make it clearer.

The Circle / Sphere

Circle is the simplest shape to draw using distance field method. Mathematically there are only 2 variables that are needed to describe a circle: Position and Radius. This means we need to calculate the distance from the center-point of the circle for every pixel on screen. Subtracting the result with the radius will give us two regions: positive values and negative values. Using 0.0 as a “boundary” we can then visualize positive values as black and negative as white.


float Circle( vec2 inputCoord, vec2 circlePos, float radius ){
return length(inputCoord-circlePos)-radius;
}

A cool thing about this function is that if you use 3D coordinates instead of 2D the result will describe a sphere instead of a circle.

World Space Warping

Manipulating the input coordinate manipulates the resulting shape. For example applying a Sine wave to the X component would make the circle oscillate from side to side;


//screen is the "world" coordinate in this case
// from -1 to 1
screen.x += sin(uTime)*0.5;
circle( screen.xy, vec2(0.0,0.0), 0.5 );

As the keen-eyed among you can see, the circle position vec2(0.0,0.0) is obsolete if offset is applied to the “world” coordinate instead. The position variable is best used for clearer position definition for example if world coordinates have more complex “global” warping.

Apply math to distance values

Highly mathematical nature of distance field drawing enables the use of more abstract and complex math on the distance values. An invaluable source of code and examples is iquilezles.org. The functions and snippets on iquilezles.org are in 3D context but will be applicable in any dimension. The following example uses polynomial blending between two circle shapes to blend them creating a metaball-like visual.


// smooth blend from iquilezles.org
float smin( float a, float b, float k )
{
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
return mix( b, a, h ) - k*h*(1.0-h);
}
// f is distance field //
float f = 10000.0;
// circle 1
f = circle( screen.xy, vec2( sin(uTime)*0.2, cos(uTime*0.5)*0.4 ), 0.2 );
// circle 2
f = smin( f, circle(screen.xy, vec2(0.0,0.0), 0.2), 0.1);

Conclusions

Although distance field rendering is not widely used in interactive graphical applications, it has a lot of potential and unique properties that make it suitable for more exotic and/or experimental use cases. Just search Distance Field on Shadertoy to experience some mindlblowing scenes rendered purely with distance functions rather than polygon mesh.

Leave a Reply

Your email address will not be published. Required fields are marked *