mirror of
https://github.com/libretro/slang-shaders.git
synced 2024-11-23 08:19:54 +00:00
404 lines
11 KiB
Plaintext
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);
|
|
}
|