Are we there yet?
What's distance?
Distance functions dist(p, q)
Distances (distance field values) can be obtained by
Input
Output:
mix
to blend the "in"-color:
colRes = mix(colIn, colRes, step(0.0, distance));
fwidth
to calculate fade-widthsmoothstep
colRes = mix(colIn, colRes, smoothstep(0.0, fwidth(distance), distance));
colRes = mix(colIn, colRes, smoothstep(0.0, glowDistance, distance));
smoothstep
fwidth
in the mix
uniform sampler2D u_SdfMap;
varying vec4 v_Color;
varying vec2 v_TexCoord;
void main() {
float distance = texture2D(u_SdfMap, v_TexCoord).a;
float width = fwidth(distance);
float alpha = smoothstep(0.5 - width, 0.5 + width, distance) * v_Color.a;
gl_FragColor = vec4(v_Color.rgb, alpha);
}
Problems with SDF's
Basic idea:
Note: there are more efficient algorithms out there.
Now let's use some shaders for that :-)
Alternative to distance maps: evaluate a distance function!
circle(pos, center, rad) = length(pos - center) - rad;
diamond(pos, center, rad) = dot(abs(pos - center), vec2(1.0)) - rad;
union(dist1, dist2) = min(dist1, dist2);
subtract(dist1, dist2) = max(-dist1, dist2);
intersect(dist1 = dist2) = max(dist1, dist2);
circle(pos, center, rad) = sqrt(pow(pos - center, 2.0)) - rad;
diamond(pos, center, rad) = dot(abs(pos - center), vec2(1.0)) - rad;
union(dist1, dist2) = min(dist1, dist2);
subtract(dist1, dist2) = max(-dist1, dist2);
intersect(dist1 = dist2) = max(dist1, dist2);
rotate(coord) = mat2(cos(ang), -sin(ang), sin(ang), cos(ang)) * coord;
Let's see what we can do with the following setup:
Slightly different scenario:
vec3 drawQuad(vec3 col, vec2 coord,
vec2 p1, vec2 p2, vec2 p3, vec2 p4,
float thickness, vec3 oldColor)
{
float sideA = sign(cross2D(coord - p1, p2 - p1));
float sideB = sign(cross2D(coord - p2, p3 - p2));
float sideC = sign(cross2D(coord - p3, p4 - p3));
float sideD = sign(cross2D(coord - p4, p1 - p4));
float dst = abs(sideA - sideB) + abs(sideB - sideC)
+ abs(sideC - sideD) + abs(sideD - sideA);
dst = clamp(dst, 0.0, 1.0);
vec3 res = mix(col, oldColor, dst);
res = drawLine(col, coord, p1, p2, thickness, res);
res = drawLine(col, coord, p2, p3, thickness, res);
res = drawLine(col, coord, p3, p4, thickness, res);
res = drawLine(col, coord, p4, p1, thickness, res);
return res;
}
Raytracing is a rendering method
Raymarching is related to raytracing
Implementation in a fragment shader:
r = generateRayForProjection(texCoord, fov);
while !(step-limit || z-limit)
d = getClosestDistanceWithScene
if (hitpoint < threshold)
break; CommenceShading
r.origin += r.dir * d;
if CommenceShading
Potentially repeat above (shadow, reflection, AO, ...)
Great overview of distance functions here
(a, b)
:
min(a, b)
max(-a, b)
max(a, b)
Shading needs a normal: evaluate the scene around the hitpoint to obtain new "hitpoints" that form the normal.
Shadows
Marching the scene from the hitpoint along the normal can be usefull for other Illumination effects:
In most real life applications we don't have many distance functions:
In order to still use the benefits, we need to combine
Let's unroll it back-to-front:
SVOs:
Voxel cone tracing:
How do we use the SVO?
How do we store things in there?
How does the geometry come into play?