#ifdef GL_ES precision mediump float; #endif #define MAX_STEPS 100 #define MAX_DIST 80. #define SURF_DIST .001 #define TAU 6.283185 #define PI 3.141592 //#define SUN_DIR vec3(0.5, 0.4, 2.) #define FOG_DENSITY 0.02 uniform vec2 u_resolution; uniform float u_time; struct Obj { float distance; // distance map int material; // material Id }; mat2 Rot(float a) { float s=sin(a), c=cos(a); return mat2(c, -s, s, c); } float sdBox(vec3 p, vec3 s) { p = abs(p)-s; return length(max(p, 0.))+min(max(p.x, max(p.y, p.z)), 0.); } vec3 applyFog(in vec3 color, in float distance) { float fogAmount = 1.0 - exp(-distance*FOG_DENSITY); vec3 fogColor = vec3(0.1, 0.18, 0.43); return mix( color, fogColor, fogAmount ); } vec3 translate(vec3 p) { p.xy *= Rot(u_time*0.4); p.yz *= Rot(u_time*0.4); return p; } float opExtrusion( in vec3 p, in float sdf, in float h ) { vec2 w = vec2( sdf, abs(p.z) - h); return min(max(w.x,w.y),0.0) + length(max(w,0.0)); } vec2 opRevolution( in vec3 p, float w ) { return vec2( length(p.xz) - w, p.y ); } vec4 opElongate( in vec3 p, in vec3 h ) { vec3 q = abs(p)-h; return vec4( max(q,0.0), min(max(q.x,max(q.y,q.z)),0.0) ); } // Scene Obj mapScene(vec3 p) { vec3 p0 = p; float dGround = p.y - 0.5*(sin(0.4*p.x+u_time*1.)+sin(1.0*p.z+u_time*1.)); dGround *=0.8; Obj ground = Obj(dGround, 0); p0.y = dGround + 0.1; float d1 = length(p0) - 0.3; Obj ob1 = Obj(d1, 1); if (ground.distance > ob1.distance) return ob1; return ground; } Obj castRay(vec3 ro, vec3 rd) { float t = 0.0; Obj res = Obj(-1., -1); for(int i=0; i MAX_DIST || res.distance < abs(SURF_DIST*t) ) break; } if (t > MAX_DIST) t = -1.0; res.distance = t; return res; } float castShadow(vec3 ro, vec3 rd) { float res = 1.0; float t = 0.0001; for(int i=0; i 20.) break; } return clamp(res,0., 1.); } vec3 calcNormal(vec3 pos) { vec2 e = vec2(.0001, 0.); vec3 n = vec3( mapScene(pos+e.xyy).distance - mapScene(pos-e.xyy).distance, mapScene(pos+e.yxy).distance - mapScene(pos-e.yxy).distance, mapScene(pos+e.yyx).distance - mapScene(pos-e.yyx).distance ); return normalize(n); } void main() { vec2 p = (2.0 * gl_FragCoord.xy - u_resolution.xy) / u_resolution.y; float angle = u_time*0.2; angle = 4.6; // comment to rotate // camera vec3 ta = vec3(0.0, .5, 0.0); vec3 ro = ta + vec3(1.*sin(angle), .7, 2.); // *cos(angle)) vec3 ww = normalize(ta-ro); vec3 uu = normalize(cross(ww, vec3(0,1,0))); vec3 vv = normalize(cross(uu,ww)); vec3 rd = normalize(p.x * uu + p.y*vv + 1.3*ww); // camera // global light vec3 col = vec3(0.1216, 0.2863, 0.5529) - 0.5*rd.y; Obj t = castRay(ro, rd); if (t.distance > 0.) { vec3 pos = ro + rd * t.distance; vec3 nor = calcNormal(pos); // vec3 r = reflect(rd, nor); vec3 outMaterial = vec3(0.1255, 0.1176, 0.1176); if (t.material == 0) { outMaterial = vec3(0.0039, 0.2235, 0.4) + sin(t.distance)*0.1; } else if (t.material == 1) { outMaterial = vec3(0.8392, 0.0118, 0.0118); } vec3 SUN_DIR = vec3(0.5+sin(u_time*0.1), 0.4, 2.0+sin(u_time*0.2)*0.5); float sun_dif = clamp(dot(nor, SUN_DIR), 0., 1.); float sun_sha = castShadow(pos + nor*0.02, SUN_DIR); float sky_dif = clamp(0.5 + 0.5 * dot(nor, vec3(0.,1.,0.)), 0., 1.); float bounce_dif = clamp(0.5 + 0.5 * dot(nor, vec3(.7,.5, 0.)), 0., 1.); // format color + what to apply col = outMaterial * vec3(2.0,1.5, .2) * sun_dif * sun_dif * sun_sha; col += outMaterial * vec3(0.0196, 0.2078, 0.4196) * sky_dif; col += outMaterial * vec3(0.051, 0.0588, 0.5686) * bounce_dif; // apply fog col = applyFog(col, t.distance); } col = pow(col, vec3(.4545)); // gamma correction gl_FragColor = vec4(col,1.0); }