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