Playing around with ray marching
Log in to post a comment.
#version 300 es precision highp float; uniform float iTime; uniform vec2 iResolution; out vec4 fragColor; // Credit to Bigwings for the framework and Hvidtfeldts for the fractal code #define MAX_STEPS 130 #define MAX_DIST 1000. #define SURF_DIST .001 float sdPlane(vec3 p) { return p.y + 1.0; } float repeat(float d, float domain) { return mod(d, domain)-domain/2.0; } float sdSierpinski(vec3 z, vec3 offset) { z.x = repeat(z.x, 4.); z.z = repeat(z.z, 4.); //int iterations = int((sin(iTime)+1.0)*8. + 1.0); int iterations = 10; float scale = clamp(sin(iTime)*0.71 + 1.7,-1.,2.0); vec3 a1 = vec3(1,1,1) + offset; vec3 a2 = vec3(-1,-1,1) + offset; vec3 a3 = vec3(1,-1,-1) + offset; vec3 a4 = vec3(-1,1,-1) + offset; vec3 c; float dist, d; int i = 0; for(int n=0; n < iterations; n++) { c = a1; dist = length(z-a1); d = length(z-a2); if (d < dist) { c = a2; dist=d; } d = length(z-a3); if (d < dist) { c = a3; dist=d; } d = length(z-a4); if (d < dist) { c = a4; dist=d; } z = scale * z - c * (scale-1.0); i++; } return (length(z)-2.0) * pow(scale, float(-i)); } float sminCubic(float a, float b, float k) { float h = max(k-abs(a-b), 0.0); return min(a, b) - h*h*h/(6.0*k*k); } float map(vec3 p) { float plane = sdPlane(p); float sierpinski1 = sdSierpinski(p, vec3(0,0,0)); float sierpinski2 = sdSierpinski(p, vec3(1,0,0)); float d = sminCubic(sierpinski1, plane,0.1); return d; } vec3 normal(vec3 p) { vec2 e = vec2(0.0, SURF_DIST*0.001); return -normalize(vec3( map(p-e.yxx)-map(p+e.yxx), map(p-e.xyx)-map(p+e.xyx), map(p-e.xxy)-map(p+e.xxy) )); } float RayMarch(vec3 ro, vec3 rd) { float d0 = 0.; float d = 1.0; vec3 p; for (int i = 0; i < MAX_STEPS; ++i) { if (d > SURF_DIST && d0 < MAX_DIST) { p = ro + rd * d0; d = map(p); d0 += d; } } return d0; } float GetLight(vec3 p) { vec3 lightPos = vec3(1, 3, -5. + iTime*10.0); //lightPos.xz += vec2(sin(iTime), cos(iTime))*2.; vec3 l = normalize(lightPos-p); vec3 n = normal(p); float dif = clamp(dot(n, l), 0., 1.); float d = RayMarch(p+n*SURF_DIST*2., l); if(d<length(lightPos-p)) dif *= .1; return dif; } float light(vec3 p, vec3 dir) { float light = GetLight(p); float total = clamp(0.5 + light, 0.0, 1.0); return total; } vec3 trace(vec3 ro, vec3 rd) { float d0 = 0.; float d = 1.0; vec3 p; for (int i = 0; i < MAX_STEPS; ++i) { if (d > SURF_DIST && d0 < MAX_DIST) { p = ro + rd * d0; d = map(p); d0 += d; } } vec3 bg = vec3(0.0,0.0,0.1); vec3 col; if (d < SURF_DIST) { // Phong shading Reinder vec3 lightPos = vec3(1, 3, -5. + iTime*10.0); vec3 worldPos = ro + d * rd; vec3 N = normalize (worldPos); vec3 V = -rd; vec3 L = normalize (lightPos - worldPos); vec3 R = reflect (-L, N); float spec = pow(max(dot(R, V), 0.0), 16.); float diff = max(dot(N, L), 0.0); float intensity = (1. / dot(lightPos - worldPos, lightPos - worldPos)); col = vec3(0.1,0.5,1)*light(p-SURF_DIST*rd, rd); + vec3(0.1,0.5,1)*pow(vec3(0.5,0.5,0.5), vec3(2.2))*spec*intensity; //col = 0.4 + 0.5*cos(light(p-SURF_DIST*rd, rd) + vec3(.5,3.5,3.5)) + vec3(0.1,0.3,0.4)*pow(vec3(0.5,0.5,0.5), vec3(2.2))*spec*intensity; } else { col = bg; } return col; } void main() { vec3 col = vec3(0.0); for(int i =-1; i<2; i++){ for(int j =-1; j<2; j++){ vec2 uv = (gl_FragCoord.xy + vec2(i,j)*.5) / iResolution.xy * 2.0 - 1.0; uv.y *= iResolution.y / iResolution.x; vec3 ro = vec3(0, 3, -4.5 + iTime*10.0); vec3 rd = normalize(vec3(uv.x-.15, uv.y-.2, 1)); col += trace(ro, rd); } } col *= 0.11111111111; col = pow(col, vec3(0.5)); fragColor = vec4(col, 1.0); }