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);
}