// stone.jpg // Abandoned base. Created by Reinder Nijhoff 2014 // @reindernijhoff // // https://www.shadertoy.com/view/XsSSRW // // #define GOLD #define BUMPMAP #define MARCHSTEPS 128 #define MARCHSTEPSREFLECTION 64 #define SPHERE //---------------------------------------------------------------------- const vec2 dropPosition = vec2(1.05,2.1); const vec3 backgroundColor = vec3(0.9,0.5,0.2); #define time iGlobalTime #define stime2 sin(time*2.) #define ctime2 cos(time*2.) //---------------------------------------------------------------------- // noises float hash( float n ) { return fract(sin(n)*43758.5453123); } float noise( in vec2 x ) { vec2 p = floor(x); vec2 f = fract(x); f = f*f*(3.0-2.0*f); float n = p.x + p.y*157.0; return mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x), mix( hash(n+157.0), hash(n+158.0),f.x),f.y); } const mat2 m2 = mat2( 0.80, -0.60, 0.60, 0.80 ); float fbm( vec2 p ) { float f = 0.0; f += 0.5000*noise( p ); p = m2*p*2.02; f += 0.2500*noise( p ); p = m2*p*2.03; f += 0.1250*noise( p ); p = m2*p*2.01; f += 0.0625*noise( p ); return f/0.9375; } mat2 rot(const in float a) { return mat2(cos(a),sin(a),-sin(a),cos(a)); } //---------------------------------------------------------------------- // distance primitives float sdBox( in vec3 p, in vec3 b ) { vec3 d = abs(p) - b; return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0)); } float sdSphere( in vec3 p, in float s ) { return length(p)-s; } float sdCylinder( in vec3 p, in vec2 h ) { vec2 d = abs(vec2(length(p.xz),p.y)) - h; return min(max(d.x,d.y),0.0) + length(max(d,0.0)); } float sdPipe( in vec3 p, in vec3 h ) { return length(h.xy-p.xy) - h.z; } float sdPPipe( in vec3 p, in vec3 h ) { return length(h.xy-p.xy) - h.z - 0.02*(max(sin(p.z*20.)-0.8,0.)); } //---------------------------------------------------------------------- // distance operators float opU( float d2, float d1 ) { return min( d1,d2); } float opS( float d2, float d1 ) { return max(-d1,d2); } vec2 opU( vec2 d2, vec2 d1 ) { return mix(d1,d2,step(d2.x,d1.x)); }//( d2.xd2.x)?-d1:d2; } //---------------------------------------------------------------------- // Map functions #ifdef SPHERE vec3 sP; #endif float xoffset( float z) { return 2.1*sin(z*0.1); } vec2 getSectorId( float z ) { float id = floor( (z+6.)/12.); return vec2( id, hash(id) ); } float map( vec3 p ) { float zorig = p.z; p = vec3( p.x+xoffset(p.z), p.y-2., mod( p.z + 6., 12. ) - 6.); float x = p.x*2., y = p.y-0.8, z = p.z; float d = -sdBox( vec3((x+y)*0.7071, (y-x)*0.7071, z), vec3(3.8,3.8,20.) ); d = opS( d, sdBox( p, vec3( 2.5, 2., 5.75 ) ) ); d = opU( d, sdPPipe( vec3(abs(p.x),p.y,p.z), vec3( 2.2, -1.7, 0.25 ) ) ); d = opU( d, sdPipe( vec3(p.x,abs(p.y-0.2),p.z), vec3( 2.4, 1.5, 0.1 ) ) ); d = opU( d, sdPipe( vec3(p.x,p.y+0.6*cos(p.z*3.1415926/12.),p.z), vec3( -2.4, 1.8, 0.12 ) ) ); d = opU( d, 2.2-p.y ); float l = distance( p.xz, dropPosition ); p.y += 0.003*sin(40.*l-6.*time)*exp(-4.*l); d = opU( d, p.y+2.03 ); d = opU( d, sdSphere( vec3( p.x, p.y-2.3, p.z*0.3), 0.2) ); if( getSectorId(zorig).y > 0.75 ) { d = opS( d, sdCylinder( vec3(p.x, p.y-9., p.z), vec2(1.5,10.) ) ); vec3 pr = vec3( stime2*p.x+ctime2*p.z, p.y-2.4, stime2*p.z-ctime2*p.x); d = opU( d, sdBox( pr, vec3(3.0,0.1,0.1) ) ); d = opU( d, sdBox( pr, vec3(0.1,0.1,3.0) ) ); } #ifdef SPHERE d = opU( d, sdSphere( vec3( p.x, p.y, zorig)-sP, 0.2) ); #endif return d; } float mapMaterial( vec3 p ) { float zorig = p.z; p = vec3( p.x+xoffset(p.z), p.y-2., mod( p.z + 6., 12. ) - 6.); float x = p.x*2., y = p.y-0.8, z = p.z; vec2 d = vec2( -sdBox( vec3((x+y)*0.7071, (y-x)*0.7071, z), vec3(3.8,3.8,20.) ), 5.); d = opS( d, vec2( sdBox( p, vec3( 2.5, 2., 5.75 ) ), 3. ) ); d = opU( d, vec2( sdPPipe( vec3(abs(p.x),p.y,p.z), vec3( 2.2, -1.7, 0.25 ) ), 1. ) ); d = opU( d, vec2( sdPipe( vec3(p.x,abs(p.y-0.2),p.z), vec3( 2.4, 1.5, 0.1 ) ), 4. ) ); d = opU( d, vec2( sdPipe( vec3(p.x,p.y+0.6*cos(p.z*3.1415926/12.),p.z), vec3( -2.4, 1.8, 0.12 ) ), 4. ) ); d = opU( d, vec2( 2.2-p.y, 5. ) ); d = opU( d, vec2( p.y+2.03, 2. ) ); d = opU( d, vec2( sdSphere( vec3( p.x, p.y-2.3, p.z*0.3), 0.2), 6.) ); if( getSectorId(zorig).y > 0.75 ) { d = opS( d, vec2( sdCylinder( vec3(p.x, p.y-4., p.z), vec2(1.5,2.) ), 5.) ); vec3 pr = vec3( stime2*p.x+ctime2*p.z, p.y-2.4, stime2*p.z-ctime2*p.x); d = opU( d, vec2( sdBox( pr, vec3(3.0,0.1,0.1) ), 4.) ); d = opU( d, vec2( sdBox( pr, vec3(0.1,0.1,3.0) ), 4.) ); } #ifdef SPHERE d = opU( d, vec2( sdSphere( vec3( p.x, p.y, zorig)-sP, 0.2), 7.) ); #endif return abs(d.y); } //---------------------------------------------------------------------- vec3 calcNormal( in vec3 pos ) { const vec2 e = vec2(1.0,-1.0)*0.005; vec3 n = normalize( e.xyy*map( pos + e.xyy ) + e.yyx*map( pos + e.yyx ) + e.yxy*map( pos + e.yxy ) + e.xxx*map( pos + e.xxx ) ); #ifdef BUMPMAP vec3 p = pos * 20.; if( abs(pos.x+xoffset(pos.z))>2.48 )n = normalize( n + 0.1*vec3(0.,fbm(p.yz)-0.5,fbm(p.zy)-0.5)); #endif return n; } vec3 int1, int2; float intersect( in vec3 ro, in vec3 rd ) { const float maxd = 60.0; const float precis = 0.001; float h = precis*2.0; float t = 0.; int1.z = -1.; for( int i=0; i < MARCHSTEPS; i++ ) { if( h < precis ) { int1 = ro+rd*t; break; } h = map( ro+rd*t ); t += h; } if( int1.z < 0. ) return -1.; ro = ro + rd*t; vec3 nor = calcNormal(ro); rd = reflect( rd, nor ); ro += 0.1 * nor; t = 0.0; h = precis*2.0; for( int i=0; i < MARCHSTEPSREFLECTION; i++ ) { if( h < precis ) { int2 = ro+rd*t; return 1.; } h = map( ro+rd*t ); t += h; } return 0.; } float softshadow( in vec3 ro, in vec3 rd, in float mint, in float maxt, in float k ) { float res = 1.0; float t = mint; for( int i=0; i<16; i++ ) { if( t>maxt ) break; float h = map( ro + rd*t ); res = min( res, k*h/t ); t += 0.03 + h; } return clamp( res, 0.0, 1.0 ); } float calcOcc( in vec3 pos, in vec3 nor ) { float totao = 0.0; float sca = 1.0; for( int i=0; i<5; i++ ) { float h = 0.02 + float(i)/4.0; float d = map( pos + h*nor ); totao += clamp(h-d,0.0,1.0)*sca; sca *= 0.4; } return clamp( 1.0 - 2.0*totao, 0.0, 1.0 ); } //---------------------------------------------------------------------- // shade vec4 texcube( sampler2D sam, in vec3 p, in vec3 n ) { vec4 x = texture( sam, p.yz ); vec4 y = texture( sam, p.zx ); vec4 z = texture( sam, p.xy ); return x*abs(n.x) + y*abs(n.y) + z*abs(n.z); } float calcLightning( in vec3 pos, in vec3 light, in vec3 nor, in float maxDist, in bool shadow ) { float sh = 1.; vec3 lig = ( light-pos ); float im = length( lig ); lig /= im; if(shadow) sh = softshadow( pos, lig, 1.02, im, 32.0 ); sh /= im; sh *= clamp(dot(nor,lig),0.,1.); return sh * (1.-smoothstep(0.,maxDist,im)); } vec3 shade( in vec3 ro, in vec3 pos, in bool shadow, in float m, in float r ) { vec3 light, col = vec3(0.); vec3 nor = calcNormal(pos); vec2 id = getSectorId(pos.z); float occ = calcOcc( pos, nor ); float dist, sh = 1., xo = xoffset(pos.z); float rc = hash(id.x+43.); float gc = hash(id.x+153.); vec3 lc = normalize(vec3( max(rc,gc), min(rc,gc), 0.1 ) ); if( id.y > 0.75 ) { light = vec3( -xo, 6.5, id*12. ); light.xz += vec2( hash(id.x+56423.), hash(id.x+124.) ) - 0.5; sh = 8.; dist = 8.; } else { light = vec3( -xo, 3.9, id*12. ); sh = 3.; dist = 5.3; if( hash(id.x+234.) < 0.15 ) lc *= 1.-clamp( 10.*(fbm( vec2(time*10., id.x) )-2.5*id.y), 0., 1.); if( pos.y > 4. ) sh*=0.5; } sh *= calcLightning( pos, light, nor, dist, shadow ); if( m < 6.5 ) col = texcube( iChannel0, pos*0.5, nor ).xyz; if( m == 1. ) col *= 0.05; if( m == 4. && pos.y > 2. ) col *= vec3(0.1,0.,0.); if( m == 4. && pos.y < 2. ) col *= vec3(0.1,0.4,1.2); if( m == 5. ) col *= (1.+0.5*fbm(pos.yz*2.))*vec3(0.2,0.1,0.05); if( m == 2. ) col *= vec3(0.8,0.6,0.4); col *= lc * occ * sh; if( m == 6. ) col = mix( 0.1*col, col*fbm(pos.xz*10.) + 0.8*lc, (1.-smoothstep( 4.15, 4.2,pos.y)) * smoothstep( 0.01, 0.04,abs(mod(pos.z+0.15,0.3)-0.15)) * smoothstep( 0.01, 0.02,abs(pos.x+xo))); col *= clamp(1.-2.*r, 0.65, 1.); col = mix( 0.05*backgroundColor, col, exp( -0.04*distance(pos, ro) ) ); return col; } //---------------------------------------------------------------------- // main void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 q = fragCoord.xy / iResolution.xy; vec2 p = -1.0 + 2.0*q; p.x *= iResolution.x / iResolution.y; if (q.y < .12 || q.y >= .88) { fragColor=vec4(0.,0.,0.,1.); return; } // camera float o = 0.2*noise(vec2(time,0.)); float z = 2.*time+o; float x = -0.95*xoffset(z); vec3 ro = vec3(x,1.7+0.02*sin(time*1.13*2.*3.1415926+o), z-1.); vec3 ta = vec3(x,1.7, z+5.); #ifdef SPHERE sP = vec3(sin(time), 1.6*cos(time*0.4), ro.z+9.+6.*sin(time*0.15) ); // ta = mix(ta,sP+vec3(0.,2.,0.),0.2); #endif if (iMouse.z>=1.) { ta.yz *= rot( -(0.5-iMouse.y/iResolution.y)*0.15 ); ta.xz *= rot( -(0.5-iMouse.x/iResolution.x)*0.5 ); } vec3 ww = normalize( ta - ro ); vec3 uu = normalize( cross(ww,vec3(0.0,1.0,0.0) ) ); vec3 vv = normalize( cross(uu,ww)); vec3 rd = normalize( -p.x*uu + p.y*vv + 2.2*ww ); vec3 col = 0.035*backgroundColor; // raymarch float ints = intersect(ro ,rd ); if( ints > -0.5 ) { float m = mapMaterial(int1); #ifdef GOLD float r = .8; #else float xo = xoffset(int1.z); vec3 p = vec3( int1.x+xo, int1.y-2., mod( int1.z + 6., 12. ) - 6.); float l = m == 2.?exp(-2.*distance( p.xz, dropPosition )):0.; float r = 0.6 * clamp(2.*(fbm( int1.xz )-0.6+l), 0.0125, 1.)*clamp(2.-int1.y, 0., 1.); if(m == 1.) r = 0.05+0.3 * fbm( int1.xz * 20. ); if(m == 7.) r = .8; if(abs(int1.x+xo) > 2.49) { r = fbm(int1.yz*0.5)*0.4* clamp(2.*(fbm( int1.yz*vec2(3.2,24.)+vec2(0.5*time,0.) )-0.5+l), 0.0, 1.) *clamp(0.5*int1.y, 0., 1.); } if(m == 4.) { r = 0.1; } #endif col = shade( ro, int1.xyz, true, m, r ); if( ints > 0.5 ) { col += r * shade( int1.xyz, int2.xyz, false, mapMaterial(int2), 0. ); } } // gamma col = pow( clamp(col*2.,0.0,1.0), vec3(0.4545) ); col *= 1.2*vec3(1.,0.99,0.95); col = clamp(1.06*col-0.03, 0., 1.); fragColor = vec4( col, 1.0 ); }