slang-shaders/procedural/reinder-tokyo.slang
2018-02-23 18:44:56 +01:00

404 lines
11 KiB
Plaintext

#version 450
// Created by Reinder Nijhoff 2014
// @reindernijhoff
//
// https://www.shadertoy.com/view/Xtf3zn
//
// car model is made by Eiffie
// shader 'Shiny Toy': https://www.shadertoy.com/view/ldsGWB
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
vec4 OutputSize;
vec4 OriginalSize;
vec4 SourceSize;
uint FrameCount;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
const vec2 madd = vec2(0.5, 0.5);
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = gl_Position.xy;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
float iGlobalTime = float(global.FrameCount)*0.025;
vec2 iResolution = global.OutputSize.xy;
#define BUMPMAP
#define MARCHSTEPS 128
#define MARCHSTEPSREFLECTION 48
#define LIGHTINTENSITY 5.
//----------------------------------------------------------------------
const vec3 backgroundColor = vec3(0.2,0.4,0.6) * 0.09;
#define time (iGlobalTime + 90.)
//----------------------------------------------------------------------
// noises
float hash( float n ) {
return fract(sin(n)*687.3123);
}
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;
}
//----------------------------------------------------------------------
// distance primitives
float udRoundBox( vec3 p, vec3 b, float r ) {
return length(max(abs(p)-b,0.0))-r;
}
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));
}
//----------------------------------------------------------------------
// distance operators
float opU( float d2, float d1 ) { return min( d1,d2); }
float opS( float d2, float d1 ) { return max(-d1,d2); }
float smin( float a, float b, float k ) { return -log(exp(-k*a)+exp(-k*b))/k; } //from iq
//----------------------------------------------------------------------
// Map functions
// car model is made by Eiffie
// shader 'Shiny Toy': https://www.shadertoy.com/view/ldsGWB
float mapCar(in vec3 p0){
vec3 p=p0+vec3(0.0,1.24,0.0);
float r=length(p.yz);
float d= length(max(vec3(abs(p.x)-0.35,r-1.92,-p.y+1.4),0.0))-0.05;
d=max(d,p.z-1.0);
p=p0+vec3(0.0,-0.22,0.39);
p.xz=abs(p.xz)-vec2(0.5300,0.9600);p.x=abs(p.x);
r=length(p.yz);
d=smin(d,length(max(vec3(p.x-0.08,r-0.25,-p.y-0.08),0.0))-0.04,8.0);
d=max(d,-max(p.x-0.165,r-0.24));
float d2=length(vec2(max(p.x-0.13,0.0),r-0.2))-0.02;
d=min(d,d2);
return d;
}
float dL; // minimal distance to light
float map( const in vec3 p ) {
vec3 pd = p;
float d;
pd.x = abs( pd.x );
pd.z *= -sign( p.x );
float ch = hash( floor( (pd.z+18.*time)/40. ) );
float lh = hash( floor( pd.z/13. ) );
vec3 pdm = vec3( pd.x, pd.y, mod( pd.z, 10.) - 5. );
dL = sdSphere( vec3(pdm.x-8.1,pdm.y-4.5,pdm.z), 0.1 );
dL = opU( dL, sdBox( vec3(pdm.x-12., pdm.y-9.5-lh, mod( pd.z, 91.) - 45.5 ), vec3(0.2,4.5, 0.2) ) );
dL = opU( dL, sdBox( vec3(pdm.x-12., pdm.y-11.5+lh, mod( pd.z, 31.) - 15.5 ), vec3(0.22,5.5, 0.2) ) );
dL = opU( dL, sdBox( vec3(pdm.x-12., pdm.y-8.5-lh, mod( pd.z, 41.) - 20.5 ), vec3(0.24,3.5, 0.2) ) );
if( lh > 0.5 ) {
dL = opU( dL, sdBox( vec3(pdm.x-12.5,pdm.y-2.75-lh, mod( pd.z, 13.) - 6.5 ), vec3(0.1,0.25, 3.2) ) );
}
vec3 pm = vec3( mod( pd.x + floor( pd.z * 4. )*0.25, 0.5 ) - 0.25, pd.y, mod( pd.z, 0.25 ) - 0.125 );
d = udRoundBox( pm, vec3( 0.245,0.1, 0.12 ), 0.005 );
d = opS( d, -(p.x+8.) );
d = opU( d, pd.y );
vec3 pdc = vec3( pd.x, pd.y, mod( pd.z+18.*time, 40.) - 20. );
// car
if( ch > 0.75 ) {
pdc.x += (ch-0.75)*4.;
dL = opU( dL, sdSphere( vec3( abs(pdc.x-5.)-1.05, pdc.y-0.55, pdc.z ), 0.025 ) );
dL = opU( dL, sdSphere( vec3( abs(pdc.x-5.)-1.2, pdc.y-0.65, pdc.z+6.05 ), 0.025 ) );
d = opU( d, mapCar( (pdc-vec3(5.,-0.025,-2.3))*0.45 ) );
}
d = opU( d, 13.-pd.x );
d = opU( d, sdCylinder( vec3(pdm.x-8.5, pdm.y, pdm.z), vec2(0.075,4.5)) );
d = opU( d, dL );
return d;
}
//----------------------------------------------------------------------
vec3 calcNormalSimple( 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 ) );
return n;
}
vec3 calcNormal( in vec3 pos ) {
vec3 n = calcNormalSimple( pos );
if( pos.y > 0.12 ) return n;
#ifdef BUMPMAP
vec2 oc = floor( vec2(pos.x+floor( pos.z * 4. )*0.25, pos.z) * vec2( 2., 4. ) );
if( abs(pos.x)<8. ) {
oc = pos.xz;
}
vec3 p = pos * 250.;
vec3 xn = 0.05*vec3(noise(p.xz)-0.5,0.,noise(p.zx)-0.5);
xn += 0.1*vec3(fbm(oc.xy)-0.5,0.,fbm(oc.yx)-0.5);
n = normalize( xn + n );
#endif
return n;
}
vec3 integer1, integer2, nor1;
vec4 lint1, lint2;
float intersect( in vec3 ro, in vec3 rd ) {
const float precis = 0.001;
float h = precis*2.0;
float t = 0.;
integer1 = integer2 = vec3( -500. );
lint1 = lint2 = vec4( -500. );
float mld = 100.;
for( int i=0; i < MARCHSTEPS; i++ ) {
h = map( ro+rd*t );
if(dL < mld){
mld=dL;
lint1.xyz = ro+rd*t;
lint1.w = abs(dL);
}
if( h < precis ) {
integer1.xyz = ro+rd*t;
break;
}
t += max(h, precis*2.);
}
if( integer1.z < -400. || t > 300.) {
// check intersection with plane y = -0.1;
float d = -(ro.y + 0.1)/rd.y;
if( d > 0. ) {
integer1.xyz = ro+rd*d;
} else {
return -1.;
}
}
ro = ro + rd*t;
nor1 = calcNormal(ro);
ro += 0.01*nor1;
rd = reflect( rd, nor1 );
t = 0.0;
h = precis*2.0;
mld = 100.;
for( int i=0; i < MARCHSTEPSREFLECTION; i++ ) {
h = map( ro+rd*t );
if(dL < mld){
mld=dL;
lint2.xyz = ro+rd*t;
lint2.w = abs(dL);
}
if( h < precis ) {
integer2.xyz = ro+rd*t;
return 1.;
}
t += max(h, precis*2.);
}
return 0.;
}
//----------------------------------------------------------------------
// shade
vec3 shade( in vec3 ro, in vec3 pos, in vec3 nor ) {
vec3 col = vec3(0.5);
if( abs(pos.x) > 15. || abs(pos.x) < 8. ) col = vec3( 0.02 );
if( pos.y < 0.01 ) {
if( abs( integer1.x ) < 0.1 ) col = vec3( 0.9 );
if( abs( abs( integer1.x )-7.4 ) < 0.1 ) col = vec3( 0.9 );
}
float sh = clamp( dot( nor, normalize( vec3( -0.3, 0.3, -0.5 ) ) ), 0., 1.);
col *= (sh * backgroundColor);
if( abs( pos.x ) > 12.9 && pos.y > 9.) { // windows
float ha = hash( 133.1234*floor( pos.y / 3. ) + floor( (pos.z) / 3. ) );
if( ha > 0.95) {
col = ( (ha-0.95)*10.) * vec3( 1., 0.7, 0.4 );
}
}
col = mix( backgroundColor, col, exp( min(max(0.1*pos.y,0.25)-0.065*distance(pos, ro),0.) ) );
return col;
}
vec3 getLightColor( in vec3 pos ) {
vec3 lcol = vec3( 1., .7, .5 );
vec3 pd = pos;
pd.x = abs( pd.x );
pd.z *= -sign( pos.x );
float ch = hash( floor( (pd.z+18.*time)/40. ) );
vec3 pdc = vec3( pd.x, pd.y, mod( pd.z+18.*time, 40.) - 20. );
if( ch > 0.75 ) { // car
pdc.x += (ch-0.75)*4.;
if( sdSphere( vec3( abs(pdc.x-5.)-1.05, pdc.y-0.55, pdc.z ), 0.25) < 2. ) {
lcol = vec3( 1., 0.05, 0.01 );
}
}
if( pd.y > 2. && abs(pd.x) > 10. && pd.y < 5. ) {
float fl = floor( pd.z/13. );
lcol = 0.4*lcol+0.5*vec3( hash( .1562+fl ), hash( .423134+fl ), 0. );
}
if( abs(pd.x) > 10. && pd.y > 5. ) {
float fl = floor( pd.z/2. );
lcol = 0.5*lcol+0.5*vec3( hash( .1562+fl ), hash( .923134+fl ), hash( .423134+fl ) );
}
return lcol;
}
float randomStart(vec2 co){return 0.8+0.2*hash(dot(co,vec2(123.42,117.853))*412.453);}
//----------------------------------------------------------------------
// 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 z = time;
float x = -10.9+1.*sin(time*0.2);
vec3 ro = vec3(x, 1.3+.3*cos(time*0.26), z-1.);
vec3 ta = vec3(-8.,1.3+.4*cos(time*0.26), z+4.+cos(time*0.04));
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 = backgroundColor;
// raymarch
float ints = intersect(ro+randomStart(p)*rd ,rd );
if( ints > -0.5 ) {
// calculate reflectance
float r = 0.09;
if( integer1.y > 0.129 ) r = 0.025 * hash( 133.1234*floor( integer1.y / 3. ) + floor( integer1.z / 3. ) );
if( abs(integer1.x) < 8. ) {
if( integer1.y < 0.01 ) { // road
r = 0.007*fbm(integer1.xz);
} else { // car
r = 0.02;
}
}
if( abs( integer1.x ) < 0.1 ) r *= 4.;
if( abs( abs( integer1.x )-7.4 ) < 0.1 ) r *= 4.;
r *= 2.;
col = shade( ro, integer1.xyz, nor1 );
if( ints > 0.5 ) {
col += r * shade( integer1.xyz, integer2.xyz, calcNormalSimple(integer2.xyz) );
}
if( lint2.w > 0. ) {
col += (r*LIGHTINTENSITY*exp(-lint2.w*7.0)) * getLightColor(lint2.xyz);
}
}
// Rain (by Dave Hoskins)
vec2 st = 256. * ( p* vec2(.5, .01)+vec2(time*.13-q.y*.6, time*.13) );
float f = noise( st ) * noise( st*0.773) * 1.55;
f = 0.25+ clamp(pow(abs(f), 13.0) * 13.0, 0.0, q.y*.14);
if( lint1.w > 0. ) {
col += (f*LIGHTINTENSITY*exp(-lint1.w*7.0)) * getLightColor(lint1.xyz);
}
col += 0.25*f*(0.2+backgroundColor);
// post processing
col = pow( clamp(col,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.);
q.y = (q.y-.12)*(1./0.76);
col *= 0.5 + 0.5*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.1 );
fragColor = vec4( col, 1.0 );
}
void main(void)
{
//just some shit to wrap shadertoy's stuff
vec2 FragmentCoord = vTexCoord.xy*global.OutputSize.xy;
FragmentCoord.y = -FragmentCoord.y;
mainImage(FragColor,FragmentCoord);
}