Last active
August 3, 2018 11:24
-
-
Save x5lcfd/21c6edfba363cf077a726fc99d133746 to your computer and use it in GitHub Desktop.
a simple distance field raymarcher
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://www.shadertoy.com/view/lltczj | |
// https://www.reddit.com/r/twotriangles/comments/1hy5qy/tutorial_1_writing_a_simple_distance_field/ | |
const int MAX_ITER = 100; | |
const float MAX_DIST = 20.0; | |
const float EPSILON = 0.001; | |
float sphere(vec3 pos, float radius) | |
{ | |
return length(pos) - radius; | |
} | |
float box(vec3 pos, vec3 size) | |
{ | |
return length(max(abs(pos) - size, 0.0)); | |
} | |
float distfunc(vec3 pos) | |
{ | |
return sphere(pos, 1.0); | |
} | |
void mainImage( out vec4 fragColor, in vec2 fragCoord ) | |
{ | |
vec3 cameraOrigin = vec3(2.0, 2.0, 2.0); | |
vec3 cameraTarget = vec3(0.0, 0.0, 0.0); | |
vec3 upDirection = vec3(0.0, 1.0, 1.0); | |
vec3 cameraDir = normalize(cameraTarget - cameraOrigin); | |
vec3 cameraRight = normalize(cross(upDirection, cameraOrigin)); | |
vec3 cameraUp = cross(cameraDir, cameraRight); | |
vec2 screenPos = -1.0 + 2.0 * fragCoord.xy / iResolution.xy; | |
screenPos.x *= iResolution.x / iResolution.y; | |
vec3 rayDir = normalize(cameraRight * screenPos.x + cameraUp * screenPos.y + cameraDir); | |
float totalDist = 0.0; | |
vec3 pos = cameraOrigin; | |
float dist = EPSILON; | |
for (int i = 0; i < MAX_ITER; i++) | |
{ | |
// Either we've hit the object or hit nothing at all, either way we should break out of the loop | |
if (dist < EPSILON || totalDist > MAX_DIST) | |
break; // If you use windows and the shader isn't working properly, change this to continue; | |
dist = distfunc(pos); // Evalulate the distance at the current point | |
totalDist += dist; | |
pos += dist * rayDir; // Advance the point forwards in the ray direction by the distance | |
} | |
if (dist < EPSILON) | |
{ | |
vec2 eps = vec2(0.0, EPSILON); | |
vec3 normal = normalize(vec3( | |
distfunc(pos + eps.yxx) - distfunc(pos - eps.yxx), | |
distfunc(pos + eps.xyx) - distfunc(pos - eps.xyx), | |
distfunc(pos + eps.xxy) - distfunc(pos - eps.xxy))); | |
float diffuse = max(0.0, dot(-rayDir, normal)); | |
float specular = pow(diffuse, 32.0); | |
vec3 color = vec3(diffuse + specular); | |
fragColor = vec4(color, 1.0); | |
} | |
else | |
{ | |
fragColor = vec4(0.0); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment