slang-shaders/procedural/leon-mam-stairs.slang
2018-02-24 02:20:43 +01:00

244 lines
7.1 KiB
Plaintext

#version 450
// M.A.M. Stairs - leon - 2017-11-24
// https://www.shadertoy.com/view/MIIBR7
// Another raymarching sketch inspired by Marc-Antoine Mathieu.
// M.A.M. Stairs by Leon Denise aka ponk
// another raymarching sketch inspired by Marc-Antoine Mathieu.
// using code from IQ, Mercury, LJ, Duke, Koltes
// made with Atom Editor GLSL viewer (that's why there is 2 space tabulations)
// 2017-11-24
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 STEPS 50.
#define VOLUME 0.01
#define PI 3.14159
#define TAU (2.*PI)
#define time iGlobalTime
#define repeat(v,c) (mod(v,c)-c/2.)
#define sDist(v,r) (length(v)-r)
mat2 rot (float a) { float c=cos(a),s=sin(a); return mat2(c,-s,s,c); }
float rng (vec2 seed) { return fract(sin(dot(seed*.1684,vec2(32.649,321.547)))*43415.); }
float sdBox( vec3 p, 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 amod (inout vec2 p, float count) { float an = TAU/count; float a = atan(p.y,p.x)+an/2.; float c = floor(a/an); c = mix(c,abs(c),step(count*.5,abs(c))); a = mod(a,an)-an/2.; p.xy = vec2(cos(a),sin(a))*length(p); return c; }
float aindex (vec2 p, float count) { float an = TAU/count; float a = atan(p.y,p.x)+an/2.; float c = floor(a/an); return mix(c,abs(c),step(count*.5,abs(c))); }
float map (vec3);
vec3 getNormal (vec3 p) { vec2 e = vec2(.001,0); return normalize(vec3(map(p+e.xyy)-map(p-e.xyy),map(p+e.yxy)-map(p-e.yxy),map(p+e.yyx)-map(p-e.yyx))); }
float hardShadow (vec3 pos, vec3 light) {
vec3 dir = normalize(light - pos);
float maxt = length(light - pos);
float t = .02;
for (float i = 0.; i <= 1.; i += 1./30.) {
float dist = map(pos + dir * t);
if (dist < VOLUME) return 0.;
t += dist;
if (t >= maxt) break;
}
return 1.;
}
float map (vec3 pos) {
float scene = 1000.;
float wallThin = .2;
float wallRadius = 8.;
float wallOffset = .2;
float wallCount = 10.;
float floorThin = .1;
float stairRadius = 5.;
float stairHeight = .4;
float stairCount = 40.;
float stairDepth = .31;
float bookCount = 100.;
float bookRadius = 9.5;
float bookSpace = 1.75;
vec3 bookSize = vec3(1.,.2,.2);
vec3 panelSize = vec3(.03,.2,.7);
vec2 cell = vec2(1.4,3.);
float paperRadius = 4.;
vec3 paperSize = vec3(.3,.01,.4);
vec3 p;
// move it
pos.y += time;
// twist it
// pos.xz *= rot(pos.y*.05+time*.1);
// pos.xz += normalize(pos.xz) * sin(pos.y*.5+time);
// holes
float holeWall = sDist(pos.xz, wallRadius);
float holeStair = sDist(pos.xz, stairRadius);
// walls
p = pos;
amod(p.xz, wallCount);
p.x -= wallRadius;
scene = min(scene, max(-p.x, abs(p.z)-wallThin));
scene = max(scene, -sDist(pos.xz, wallRadius-wallOffset));
// floors
p = pos;
p.y = repeat(p.y, cell.y);
float disk = max(sDist(p.xz, 1000.), abs(p.y)-floorThin);
disk = max(disk, -sDist(pos.xz, wallRadius));
scene = min(scene, disk);
// stairs
p = pos;
float stairIndex = amod(p.xz, stairCount);
p.y -= stairIndex*stairHeight;
p.y = repeat(p.y, stairCount*stairHeight);
float stair = sdBox(p, vec3(100,stairHeight,stairDepth));
scene = min(scene, max(stair, max(holeWall, -holeStair)));
p = pos;
p.xz *= rot(PI/stairCount);
stairIndex = amod(p.xz, stairCount);
p.y -= stairIndex*stairHeight;
p.y = repeat(p.y, stairCount*stairHeight);
stair = sdBox(p, vec3(100,stairHeight,stairDepth));
scene = min(scene, max(stair, max(holeWall, -holeStair)));
p = pos;
p.y += stairHeight*.5;
p.y -= stairHeight*stairCount*atan(p.z,p.x)/TAU;
p.y = repeat(p.y, stairCount*stairHeight);
scene = min(scene, max(max(sDist(p.xz, wallRadius), abs(p.y)-stairHeight), -holeStair));
// books
p = pos;
p.y -= cell.y*.5;
vec2 seed = vec2(floor(p.y/cell.y), 0);
p.y = repeat(p.y, cell.y);
p.xz *= rot(PI/wallCount);
seed.y += amod(p.xz, wallCount)/10.;
seed.y += floor(p.z/(bookSize.z*bookSpace));
p.z = repeat(p.z, bookSize.z*bookSpace);
float salt = rng(seed);
bookSize.x *= .5+.5*salt;
bookSize.y += salt;
bookSize.z *= .5+.5*salt;
p.x -= bookRadius + wallOffset;
p.x += cos(p.z*2.) - bookSize.x - salt * .25;
p.x += .01*smoothstep(.99,1.,sin(p.y*(1.+10.*salt)));
scene = min(scene, max(sdBox(p, vec3(bookSize.x,100.,bookSize.z)), p.y-bookSize.y));
// panel
p = pos;
p.y = repeat(p.y, cell.y);
p.xz *= rot(PI/wallCount);
amod(p.xz, wallCount);
p.x -= wallRadius;
float panel = sdBox(p, panelSize);
float pz = p.z;
p.z = repeat(p.z, .2+.3*salt);
panel = min(panel, max(sdBox(p, vec3(.1,.1,.04)), abs(pz)-panelSize.z*.8));
scene = min(scene, panel);
// papers
p = pos;
p.y -= stairHeight;
p.y += time*2.;
p.xz *= rot(PI/stairCount);
float ry = 8.;
float iy = floor(p.y/ry);
salt = rng(vec2(iy));
float a = iy;
p.xz -= vec2(cos(a),sin(a))*paperRadius;
p.y = repeat(p.y, ry);
p.xy *= rot(p.z);
p.xz *= rot(PI/4.+salt+time);
scene = min(scene, sdBox(p, paperSize));
return scene;
}
vec3 getCamera (vec3 eye, vec2 uv) {
vec3 lookAt = vec3(0.);
#ifdef MOUSE
float click = clamp(iMouse.w,0.,1.);
lookAt.x += mix(0.,((iMouse.x/iResolution.x)*2.-1.) * 10., click);
lookAt.y += mix(0.,iMouse.y/iResolution.y * 10., click);
#else
float click = clamp(0.,0.,1.);
lookAt.x += mix(0.,((0./iResolution.x)*2.-1.) * 10., click);
lookAt.y += mix(0.,0./iResolution.y * 10., click);
#endif
float fov = .65;
vec3 forward = normalize(lookAt - eye);
vec3 right = normalize(cross(vec3(0,1,0), forward));
vec3 up = normalize(cross(forward, right));
return normalize(fov * forward + uv.x * right + uv.y * up);
}
float getLight (vec3 pos, vec3 eye) {
vec3 light = vec3(-.5,7.,1.);
vec3 normal = getNormal(pos);
vec3 view = normalize(eye-pos);
float shade = dot(normal, view);
shade *= hardShadow(pos, light);
return shade;
}
vec4 raymarch () {
vec2 uv = (gl_FragCoord.xy-.5*iResolution.xy)/iResolution.y;
float dither = rng(uv+fract(time));
vec3 eye = vec3(0,5,-4.5);
vec3 ray = getCamera(eye, uv);
vec3 pos = eye;
float shade = 0.;
for (float i = 0.; i <= 1.; i += 1./STEPS) {
float dist = map(pos);
if (dist < VOLUME) {
shade = 1.-i;
break;
}
dist *= .5 + .1 * dither;
pos += ray * dist;
}
vec4 color = vec4(shade);
color *= getLight(pos, eye);
color = smoothstep(.0, .5, color);
color = sqrt(color);
return color;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
fragColor = raymarch();
}
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);
}