397 lines
11 KiB
Forth
397 lines
11 KiB
Forth
|
// 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.x<d1.x)? d2:d1; }
|
||
|
vec2 opS( vec2 d2, vec2 d1 ) { return mix(-d1,d2,step(-d1.x,d2.x)); }//(-d1.x>d2.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 );
|
||
|
}
|