slang-shaders/procedural/leon-tribute-to-marc-antoine-mathieu.slang
2018-02-24 02:20:43 +01:00

240 lines
7.5 KiB
Plaintext

#version 450
// Tribute to Marc-Antoine Mathieu - leon - 2017-11-21
// https://www.shadertoy.com/view/XlfBR7
// Raymarching skectch inspired by the work of Marc-Antoine Mathieu
// Raymarching sketch inspired by the work of Marc-Antoine Mathieu
// Leon 2017-11-21
// using code from IQ, Mercury, LJ, Duke, Koltes
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;
// tweak it
#define donut 30.
#define cell 4.
#define height 2.
#define thin .04
#define radius 15.
#define speed 1.
#define STEPS 100.
#define VOLUME 0.001
#define PI 3.14159
#define TAU (2.*PI)
#define time iGlobalTime
// raymarching toolbox
float rng (vec2 seed) { return fract(sin(dot(seed*.1684,vec2(54.649,321.547)))*450315.); }
mat2 rot (float a) { float c=cos(a),s=sin(a); return mat2(c,-s,s,c); }
float sdSphere (vec3 p, float r) { return length(p)-r; }
float sdCylinder (vec2 p, float r) { return length(p)-r; }
float sdDisk (vec3 p, vec3 s) { return max(max(length(p.xz)-s.x, s.y), abs(p.y)-s.z); }
float sdIso(vec3 p, float r) { return max(0.,dot(p,normalize(sign(p))))-r; }
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 sdTorus( vec3 p, vec2 t ) { vec2 q = vec2(length(p.xz)-t.x,p.y); return length(q)-t.y; }
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 amodIndex (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))); return c; }
float repeat (float v, float c) { return mod(v,c)-c/2.; }
vec2 repeat (vec2 v, vec2 c) { return mod(v,c)-c/2.; }
vec3 repeat (vec3 v, float c) { return mod(v,c)-c/2.; }
float smoo (float a, float b, float r) { return clamp(.5+.5*(b-a)/r, 0., 1.); }
float smin (float a, float b, float r) { float h = smoo(a,b,r); return mix(b,a,h)-r*h*(1.-h); }
float smax (float a, float b, float r) { float h = smoo(a,b,r); return mix(a,b,h)+r*h*(1.-h); }
vec2 displaceLoop (vec2 p, float r) { return vec2(length(p.xy)-r, atan(p.y,p.x)); }
float map (vec3);
float getShadow (vec3 pos, vec3 at, float k) {
vec3 dir = normalize(at - pos);
float maxt = length(at - pos);
float f = 01.;
float t = VOLUME*50.;
for (float i = 0.; i <= 1.; i += 1./15.) {
float dist = map(pos + dir * t);
if (dist < VOLUME) return 0.;
f = min(f, k * dist / t);
t += dist;
if (t >= maxt) break;
}
return f;
}
vec3 getNormal (vec3 p) { vec2 e = vec2(.01,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))); }
void camera (inout vec3 p) {
p.xz *= rot(PI/8.);
p.yz *= rot(PI/6.);
}
float windowCross (vec3 pos, vec4 size, float salt) {
vec3 p = pos;
float sx = size.x * (.6+salt*.4);
float sy = size.y * (.3+salt*.7);
vec2 sxy = vec2(sx,sy);
p.xy = repeat(p.xy+sxy/2., sxy);
float scene = sdBox(p, size.zyw*2.);
scene = min(scene, sdBox(p, size.xzw*2.));
scene = max(scene, sdBox(pos, size.xyw));
return scene;
}
float window (vec3 pos, vec2 dimension, float salt) {
float thinn = .008;
float depth = .04;
float depthCadre = .06;
float padding = .08;
float scene = windowCross(pos, vec4(dimension,thinn,depth), salt);
float cadre = sdBox(pos, vec3(dimension, depthCadre));
cadre = max(cadre, -sdBox(pos, vec3(dimension - padding, depthCadre*2.)));
scene = min(scene, cadre);
return scene;
}
float boxes (vec3 pos, float salt) {
vec3 p = pos;
float ry = cell * .43*(.3+salt);
float rz = cell * .2*(.5+salt);
float salty = rng(vec2(floor(pos.y/ry), floor(pos.z/rz)));
pos.y = repeat(pos.y, ry);
pos.z = repeat(pos.z, rz);
float scene = sdBox(pos, vec3(.1+.8*salt+salty,.1+.2*salt,.1+.2*salty));
scene = max(scene, sdBox(p, vec3(cell*.2)));
return scene;
}
float map (vec3 pos) {
vec3 camOffset = vec3(-4,0,0.);
float scene = 1000.;
vec3 p = pos + camOffset;
float segments = PI*radius;
float indexX, indexY, salt;
vec2 seed;
// donut distortion
vec3 pDonut = p;
pDonut.x += donut;
pDonut.y += radius;
pDonut.xz = displaceLoop(pDonut.xz, donut);
pDonut.z *= donut;
pDonut.xzy = pDonut.xyz;
pDonut.xz *= rot(time*.05*speed);
// ground
p = pDonut;
scene = min(scene, sdCylinder(p.xz, radius-height));
// walls
p = pDonut;
float py = p.y + time * speed;
indexY = floor(py / (cell+thin));
p.y = repeat(py, cell+thin);
scene = min(scene, max(abs(p.y)-thin, sdCylinder(p.xz, radius)));
amod(p.xz, segments);
p.x -= radius;
scene = min(scene, max(abs(p.z)-thin, p.x));
// horizontal windot
p = pDonut;
p.xz *= rot(PI/segments);
py = p.y + time * speed;
indexY = floor(py / (cell+thin));
p.y = repeat(py, cell+thin);
indexX = amodIndex(p.xz, segments);
amod(p.xz, segments);
seed = vec2(indexX, indexY);
salt = rng(seed);
p.x -= radius;
vec2 dimension = vec2(.75,.5);
p.x += dimension.x * 1.5;
scene = max(scene, -sdBox(p, vec3(dimension.x, .1, dimension.y)));
scene = min(scene, window(p.xzy, dimension, salt));
// vertical window
p = pDonut;
py = p.y + cell/2. + time * speed;
indexY = floor(py / (cell+thin));
p.y = repeat(py, cell+thin);
indexX = amodIndex(p.xz, segments);
amod(p.xz, segments);
seed = vec2(indexX, indexY);
salt = rng(seed);
p.x -= radius;
dimension.y = 1.5;
p.x += dimension.x * 1.25;
scene = max(scene, -sdBox(p, vec3(dimension, .1)));
scene = min(scene, window(p, dimension, salt));
// elements
p = pDonut;
p.xz *= rot(PI/segments);
py = p.y + cell/2. + time * speed;
indexY = floor(py / (cell+thin));
p.y = repeat(py, cell+thin);
indexX = amodIndex(p.xz, segments);
amod(p.xz, segments);
seed = vec2(indexX, indexY);
salt = rng(seed);
p.x -= radius - height;
scene = min(scene, boxes(p, salt));
return scene;
}
void mainImage( out vec4 color, in vec2 coord ) {
vec2 uv = (coord.xy-.5*iResolution.xy)/iResolution.y;
vec3 eye = vec3(0,0,-20);
vec3 ray = normalize(vec3(uv, 1.3));
camera(eye);
camera(ray);
float dither = rng(uv+fract(time));
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;
}
vec3 light = vec3(40.,100.,-10.);
float shadow = getShadow(pos, light, 4.);
color = vec4(1);
color *= shade;
color *= shadow;
color = smoothstep(.0, .5, color);
color.rgb = sqrt(color.rgb);
}
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);
}