Created
January 12, 2022 20:28
-
-
Save justinmeiners/0b7a2dbd6ff32ca72416fdbdcef2f4c9 to your computer and use it in GitHub Desktop.
This file contains 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
float g_epsilon = 0.002; | |
float g_max = 50.0; | |
float sdSphere( vec3 toCenter, float s ) | |
{ | |
return length(toCenter)-s; | |
} | |
float sdBox( vec3 p, vec3 b ) | |
{ | |
vec3 q = abs(p) - b; | |
return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0); | |
} | |
float sdPlane(vec3 p, vec3 n) | |
{ | |
return dot(n, p); | |
} | |
vec2 worldDistance(vec3 p) | |
{ | |
vec3 sphereCenter = vec3(2.0, 0.0, 0.0); | |
float dist1 = sdSphere(p - sphereCenter, 1.0); | |
float dist2 = sdBox(p, vec3(1.0, 1.0, 1.0)); | |
float dist3 = sdPlane(p - vec3(0.0, -2.0, 0.0), vec3(0.0, 1.0, 0.0)); | |
if ((dist1 < dist2) && (dist1 < dist3)) | |
{ | |
return vec2(dist1, 0.0); | |
} | |
else if (dist2 < dist3) | |
{ | |
return vec2(dist2, 1.0); | |
} | |
else | |
{ | |
return vec2(dist3, 2.0); | |
} | |
} | |
vec3 worldColor(vec3 p, int id) | |
{ | |
switch (id) | |
{ | |
case 0: | |
return vec3(1.0, 0.0, 0.0); | |
case 1: | |
return vec3(0.0, 0.0, 1.0); | |
case 2: | |
return vec3( | |
(mod(p.x, 1.0) - 0.5) * (mod(p.z, 1.0) - 0.5) > 0.0, | |
1.0, | |
1.0 | |
); | |
} | |
return vec3(0.0, 0.0, 0.0); | |
} | |
vec3 worldNormal(vec3 p, int id) | |
{ | |
switch (id) | |
{ | |
case 0: | |
return normalize(p - vec3(2.0, 0.0, 0.0)); | |
case 1: | |
if ((abs(p.x) > abs(p.y)) && (abs(p.x) > abs(p.z))) | |
{ | |
return normalize(vec3(p.x, 0.0, 0.0)); | |
} | |
else if (abs(p.y) > abs(p.z)) | |
{ | |
return normalize(vec3(0.0, p.y, 0.0)); | |
} | |
else | |
{ | |
return normalize(vec3(0.0, 0.0, p.z)); | |
} | |
break; | |
case 2: | |
return vec3(0.0, 1.0, 0.0); | |
} | |
return vec3(0.0, 1.0, 0.0); | |
} | |
vec4 raytrace(vec3 ro, vec3 rd) | |
{ | |
vec4 color = vec4(0.4 * rd.x, 0.4 * (rd.x + 1.0) / 2.0, 1.0, 1.0); | |
float t = 0.0; | |
const int maxSteps = 60; | |
for(int i = 0; i < maxSteps; ++i) | |
{ | |
vec3 p = ro + rd * t; | |
vec2 hitInfo = worldDistance(p); | |
float d = hitInfo.x; | |
if (d < g_epsilon) | |
{ | |
vec3 n = worldNormal(p, int(hitInfo.y)); | |
vec3 l = normalize(vec3(1.0, 1.0, 0.0)); | |
vec3 base = worldColor(p, int(hitInfo.y)); | |
color = vec4(max(dot(n, l), 0.2) * base, 1.0); | |
break; | |
} | |
else if (d > g_max) | |
{ | |
color = vec4(0.0, float(i) / 32.0, 0.0, 1.0); | |
break; | |
} | |
t += d; | |
} | |
return color; | |
} | |
mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) | |
{ | |
vec3 cw = normalize(ta-ro); | |
vec3 cp = vec3(sin(cr), cos(cr),0.0); | |
vec3 cu = normalize( cross(cw,cp) ); | |
vec3 cv = normalize( cross(cu,cw) ); | |
return mat3( cu, cv, cw ); | |
} | |
void mainImage( out vec4 fragColor, in vec2 fragCoord ) | |
{ | |
vec2 uv = (fragCoord.xy / iResolution.xy) * 2.0 - 1.0; | |
uv.x *= iResolution.x/iResolution.y; | |
float time = 15.0 + iTime; | |
vec3 ro = vec3( -0.8+3.5*cos(0.5*time), 3.0, 0.8 + 3.5*sin(0.5*time) ); | |
vec3 ta = vec3( 0.0, -0.4, 0.0 ); | |
// camera-to-world transformation | |
mat3 ca = setCamera( ro, ta, 0.0 ); | |
// ray direction | |
vec3 rd = ca * normalize( vec3(uv.xy,2.0) ); | |
fragColor = raytrace(ro, rd); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment