v4k-git-backup/demos/art/shadertoys/XsSSRW.fs

397 lines
11 KiB
Forth
Raw Normal View History

2023-08-10 14:30:56 +00:00
// 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 );
}