mirror of
https://github.com/libretro/slang-shaders.git
synced 2024-11-23 08:19:54 +00:00
863 lines
31 KiB
Plaintext
863 lines
31 KiB
Plaintext
#version 450
|
|
// Portal Gameplay
|
|
// ciberxtrem - https://www.shadertoy.com/view/XlsSzM
|
|
|
|
// Inspired in Portal, Chamber 8.
|
|
|
|
// Note: Set the APPLY_COLORS and APPLY_SHADOW to 1 to see all colors and shadows
|
|
|
|
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;
|
|
|
|
// Thanks iq and the Shadertoy comunity for all the shared knowledge! :)
|
|
|
|
// Set this to 1 to enable colors!
|
|
#define APPLY_COLORS 0
|
|
#define APPLY_SHADOW 0
|
|
//---------------------------
|
|
|
|
#define PI 3.14159265359
|
|
|
|
struct LightStruct {
|
|
vec3 pos;
|
|
vec3 color;
|
|
};
|
|
|
|
struct PortalStruct {
|
|
vec3 pos;
|
|
vec3 front;
|
|
float rotateY;
|
|
float time;
|
|
};
|
|
|
|
struct StateStruct
|
|
{
|
|
vec3 posStart;
|
|
vec3 posEnd;
|
|
float lerptime;
|
|
float duration;
|
|
float isEnterTime;
|
|
float enterPortal;
|
|
float exitPortal;
|
|
};
|
|
|
|
struct OrientationStruct
|
|
{
|
|
vec3 orientation;
|
|
float lerptime;
|
|
float duration;
|
|
};
|
|
|
|
PortalStruct portalA;
|
|
PortalStruct portalB;
|
|
|
|
PortalStruct portalsA[8];
|
|
StateStruct states[10];
|
|
OrientationStruct orientations[15];
|
|
LightStruct lights[3];
|
|
|
|
float t;
|
|
vec3 position;
|
|
vec3 orientation;
|
|
float ambient = 0.05;
|
|
vec3 ambientcolor;
|
|
|
|
vec3 rotateY(vec3 p, float a){
|
|
return vec3(
|
|
p.x*cos(a) + p.z*sin(a),
|
|
p.y,
|
|
p.z*cos(a) - p.x*sin(a)
|
|
);
|
|
}
|
|
|
|
float hash( float n ) {
|
|
return fract(sin(n)*43758.5453123);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
float dBox(vec3 p, vec3 hsize)
|
|
{
|
|
return length(max(abs(p)-hsize,0.0));
|
|
}
|
|
|
|
float udRoundBox( vec3 p, vec3 b, float r )
|
|
{
|
|
return length(max(abs(p)-b,0.0))-r;
|
|
}
|
|
|
|
float sdCappedCylinder( vec3 p, 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));
|
|
}
|
|
//-------------------------------
|
|
|
|
// Scene
|
|
float dElipse(vec3 p, vec3 hsize, float globalSize)
|
|
{
|
|
float d = length(max(abs(p)-hsize,0.0));
|
|
vec3 q = p;
|
|
q.y *= 0.6;
|
|
return max(d, length(q)-max(max(hsize.x, hsize.y)*globalSize, hsize.z));
|
|
}
|
|
|
|
vec2 dStructure(vec3 p)
|
|
{
|
|
// Front
|
|
vec2 res = vec2(-1., -1.);
|
|
vec3 q = p - vec3(0., 0.5, 28.25);
|
|
vec2 c = vec2(3., 6.2);
|
|
vec3 q2 = q; q2.xy = mod(q2.xy,c.xy)-0.5*c.xy;
|
|
float d = udRoundBox(q2, vec3(1.35, 3., 1.0), 0.25);
|
|
q = p - vec3(0.0, 9.5, 28.); // Hole for exit
|
|
float d2 = udRoundBox(q, vec3(3.0, 3.25, 2.0), 0.1);
|
|
d = max(d,-d2);
|
|
res = vec2(d, 24.);
|
|
//Back
|
|
q = p - vec3(0., 3.5, -28.0);
|
|
c = vec2(3., 6.2);
|
|
q.x = mod(q.x,c.x)-0.5*c.x;
|
|
d = udRoundBox(q, vec3(1.35, 3., 1.0), 0.25);
|
|
res = mix(vec2(d, 24.), res, step(res.x, d));
|
|
q = p - vec3(0., 0.6, -28.01); // Brown block
|
|
c = vec2(3., 3.0);
|
|
q.xy = mod(q.xy,c.xy)-0.5*c.xy;
|
|
d = udRoundBox(q, vec3(1.35, 1.35, 1.0), 0.25);
|
|
q = p - vec3(0.0, 9.5, -28.); // Hole for exit
|
|
d2 = udRoundBox(q, vec3(3.0, 3.25, 2.0), 0.1);
|
|
d = max(d,-d2);
|
|
res = mix(vec2(d, 20.), res, step(res.x, d));
|
|
//Exit
|
|
vec3 p2 = p; p2.z = abs(p.z);
|
|
q = p2 - vec3(0.0, 9.5, 30.5);
|
|
d = udRoundBox(q, vec3(3.0, 3.25, 0.1), 0.1);
|
|
if(d<res.x){res = vec2(d, 10.);} // magic panel
|
|
q2 = q - vec3(4.5, 0., -1.); q2.x += abs(sin(length(1.5+abs(q2.y)*0.36)));
|
|
d = udRoundBox(q2, vec3(1.5, 4.5, 2.0), 0.1);
|
|
q2 = q - vec3(-4.5, 0., -1.); q2.x -= abs(sin(length(1.5+abs(q2.y)*0.36)));
|
|
d2 = udRoundBox(q2, vec3(1.5, 4.5, 2.0), 0.1);
|
|
d = min(d, d2);
|
|
res = mix(vec2(d, 11.), res, step(res.x, d));
|
|
//Left
|
|
q = p - vec3(-16., 0.5, 0.0);
|
|
c = vec2(3.0, 6.2);
|
|
q2 = q; q2.zy = mod(q2.zy,c)-0.5*c;
|
|
d = udRoundBox(q2, vec3(1., 3., 1.35), 0.25);
|
|
res = mix(vec2(d, 24.), res, step(res.x, d));
|
|
//Right
|
|
q = p - vec3(16.0, 0.5, 0.0);
|
|
c = vec2(3.0, 6.2);
|
|
q.zy = mod(q.zy,c)-0.5*c;
|
|
d = udRoundBox(q, vec3(1., 3., 1.35), 0.25);
|
|
// Hole for window
|
|
q = p - vec3(15.0, 15.5, -9.0);
|
|
d2 = udRoundBox(q, vec3(2.0, 3., 6.0), 0.02);
|
|
d = max(d, -d2);
|
|
res = mix(vec2(d, 24.), res, step(res.x, d));
|
|
// Column
|
|
q = p - vec3(0., 0.6, -23.90);
|
|
c = vec2(3., 3.0);
|
|
q.xy = mod(q.xy,c)-0.5*c;
|
|
d = udRoundBox(q, vec3(1.35, 1.35, 2.70), 0.25);
|
|
d = max(d, -(p.x-6.1));
|
|
res = mix(vec2(d, 24.), res, step(res.x, d));
|
|
// Ceiling
|
|
q = p - vec3(0., 20.4, .0);
|
|
c = vec2(3.0, 3.0);
|
|
q2 = q; q2.xz = mod(q2.xz,c)-0.5*c;
|
|
d = udRoundBox(q2, vec3(1.35, 1., 1.35), 0.25);
|
|
d2 = length(q)-6.;
|
|
d = max(d, -d2);
|
|
res = mix(vec2(d, 23.), res, step(res.x, d));
|
|
//Window
|
|
q = p - vec3(16.0, 15.5, -9.0);
|
|
d = udRoundBox(q, vec3(1.25, 3., 6.0), 0.02); // framework
|
|
d2 = udRoundBox(q, vec3(1.5, 2.6, 5.6), 0.02);
|
|
d = max(d, -d2);
|
|
d = min(d, udRoundBox(q, vec3(1.2, 3., 0.2), 0.02)); // bars
|
|
res = mix(vec2(d, 7.), res, step(res.x, d));
|
|
d = udRoundBox(q, vec3(1.0, 2.6, 5.6), 0.1);
|
|
d -= smoothstep(-1., 1., cos(p.y*15.)) * 0.0025;
|
|
res = mix(vec2(d, 5.), res, step(res.x, d));
|
|
// Dome
|
|
q = p-vec3(0., 21.5, 0.);
|
|
q.y *= 1.0;
|
|
d = length(q) - 6.;
|
|
res = mix(vec2(d, 9.), res, step(res.x, d));
|
|
//Turbina
|
|
q = p - vec3(0.0, 15.0, 0.0);
|
|
q = rotateY(q, t);
|
|
d = dBox(q, vec3(5.5, 0.05, 0.4));
|
|
d2 = dBox(q, vec3(0.4, 0.05, 5.5));
|
|
d = min(d, d2);
|
|
d2 = sdCappedCylinder(q-vec3(0., 0.5, 0.), vec2(0.4, 0.5));
|
|
d = min(d, d2);
|
|
res = mix(vec2(d, 4.), res, step(res.x, d));
|
|
// Front railing
|
|
q = p - vec3(-5.5, 6.5, 23.2);
|
|
d = dBox(q, vec3(9.0, 0.1, 4.0));
|
|
res = mix(vec2(d, 8.), res, step(res.x, d));
|
|
d = udRoundBox(q-vec3(0., 1.6, -4.0), vec3(9.0, 1.7, 0.05), 0.02);
|
|
d2 = udRoundBox(q-vec3(0., 1.6, -4.0), vec3(8.8, 1.5, 0.5), 0.02);
|
|
d = max(d, -d2);
|
|
d = min(d, udRoundBox(q-vec3(8.9, 3.2, 0.0), vec3(0.10, 0.10, 4.0), 0.01));
|
|
res = mix(vec2(d, 7.), res, step(res.x, d));
|
|
|
|
// Back railing
|
|
q = p - vec3(-0.5, 6.5, -24.2);
|
|
d = dBox(q, vec3(6.0, 0.1, 3.0));
|
|
res = mix(vec2(d, 8.), res, step(res.x, d));
|
|
d = udRoundBox(q-vec3(0.5, 1.6, 3.2), vec3(6.0, 1.7, 0.1), 0.02);
|
|
d2 = udRoundBox(q-vec3(0.5, 1.6, 3.2), vec3(5.8, 1.5, 1.0), 0.02);
|
|
d = max(d, -d2);
|
|
res = mix(vec2(d, 7.), res, step(res.x, d));
|
|
|
|
return res;
|
|
}
|
|
|
|
vec2 dWater(vec3 p)
|
|
{
|
|
vec3 q = p - vec3(0., -0., .0);
|
|
float d = dBox(q, vec3(20., 0.2, 40.));
|
|
d-=smoothstep(-1., 1., cos(p.x*2.1+t*2.)*cos(p.z*3.5+t*1.6))*0.01;
|
|
float d2 = smoothstep(-1., 1., cos(length(p.xz)*2.-t))*0.05;
|
|
d2 = mix(0., d2, smoothstep(1.0, 10., length(q.xz)));
|
|
d -= d2;
|
|
|
|
return vec2(d, 3.);
|
|
}
|
|
|
|
vec2 dPlatforms(vec3 p)
|
|
{
|
|
// Front Right Platform
|
|
vec2 res = vec2(-1, -1.);
|
|
vec3 q = p - vec3(11.5, 7., 7.0);
|
|
vec2 c = vec2(3.0);
|
|
vec3 q2 = q; q2.xz = mod(q2.xz+vec2(0., 1.0),c)-0.5*c;
|
|
float d = udRoundBox(q2, vec3(1.415, 0.2, 1.415), 0.1);
|
|
d = max(d, q.z-5.); d = max(d, -(q.z+4.)); d = max(d, -(q.x+6.));
|
|
res = vec2(d, 21.);
|
|
//Tube
|
|
d = sdCappedCylinder(q-vec3(0., -4., 0.), vec2(0.65, 3.));
|
|
d = min(d, sdCappedCylinder(q-vec3(0., -7.5, 0.), vec2(1.0, 2.)));
|
|
res = mix(vec2(d, 6.), res, step(res.x, d));
|
|
// Front Left Platform
|
|
vec3 leftPlatPos = vec3(-10.0, 7., -2.0);
|
|
if(t > 29.0){
|
|
float phase = (t-29.)/7.;
|
|
float seq = mod(phase, 2.);
|
|
leftPlatPos =mix(vec3(-10, 7., -2.), vec3(-11.6, 7., -23.0), fract(phase));
|
|
}
|
|
q = p - leftPlatPos;
|
|
d = udRoundBox(q, vec3(3.8, 0.02, 3.8), 0.01);
|
|
res = mix(vec2(d, 22.), res, step(res.x, d));
|
|
// Border
|
|
d = udRoundBox(q, vec3(4.0, 0.05, 4.0), 0.1);
|
|
float d2 = udRoundBox(q, vec3(3.5, 0.1, 3.5), 0.1);
|
|
d = max(d, -d2);
|
|
res = mix(vec2(d, 24.), res, step(res.x, d));
|
|
// Crosses
|
|
d = udRoundBox(q-vec3(0., -0.05, 0.), vec3(4.0, 0.08, 0.1), 0.05);
|
|
d = min(d, udRoundBox(q-vec3(0., -0.05, 0.), vec3(0.1, 0.08, 4.0), 0.05));
|
|
res = mix(vec2(d, 24.), res, step(res.x, d));
|
|
//Tube
|
|
d = sdCappedCylinder(q-vec3(0., -1.5, 0.), vec2(0.65, 1.6));
|
|
d = min(d, sdCappedCylinder(q-vec3(0., -5.0, 0.), vec2(1.0, 2.)));
|
|
res = mix(vec2(d, 6.), res, step(res.x, d));
|
|
|
|
return res;
|
|
}
|
|
|
|
vec4 dBloomObjects(vec3 p)
|
|
{
|
|
vec4 res = vec4(-1, -1, 999., 0.);
|
|
//Lamp
|
|
vec3 q = p - vec3(0.0, 14.6, 0.0);
|
|
q.y *= 1.4;
|
|
float d = length(q)-0.8;
|
|
res.zw = vec2(d, 1.);
|
|
res.xy = vec2(d, 7.);
|
|
// FireballBaseStart
|
|
q = p - vec3(10.5, 9.5, 27.5);
|
|
d = length(vec3(q.x, q.y, q.z))-2.5;
|
|
d = max(d, -(q.z+1.5));
|
|
float d2 = (length((vec3(q.x, q.y, (q.z+1.5)*0.8)))-1.5); d2 += cos((p.z+0.5)*4.5)*0.1;
|
|
d = min(d, d2);
|
|
d += mix(0., 1., smoothstep(0.6, 1., cos(q.x*2.)*cos(q.y*2.)*cos(q.z+1.)))*1.0;
|
|
res.xy = mix(vec2(d, 12.), res.xy, step(res.x, d));
|
|
// FireballBaseEnd
|
|
q = p - vec3(-15.9, 9.5, -12.0);
|
|
q = rotateY(q, PI*0.5);
|
|
d = length(vec3(q.x, q.y, q.z))-2.5;
|
|
d = max(d, -(q.z+1.5));
|
|
d = max(d, -(length(q-vec3(0., 0., -5.6))-4.5));
|
|
d += mix(0., 1., smoothstep(0.5, 1., cos(q.x*2.)*cos(q.y*2.)*cos(q.z+1.)))*1.0;
|
|
res.xy = mix(vec2(d, 12.), res.xy, step(res.x, d));
|
|
// Redpoint
|
|
q = p - vec3(-15.4, 9.5, -12.0);
|
|
d = length(q)-0.9;
|
|
res.xy = mix(vec2(d, 22.), res.xy, step(res.x, d));
|
|
res.zw = mix(vec2(d, 0.),res.zw, step(res.z, d));
|
|
// RedPoint
|
|
q = p - vec3(14.8, 9.5, -12.0);
|
|
d = length(q)-0.01;
|
|
res.xy = mix(vec2(d, 22.), res.xy, step(res.x, d));
|
|
res.zw = mix(vec2(d, 0.),res.zw, step(res.z, d));
|
|
// Fireball
|
|
vec3 firePos = vec3(0.);
|
|
if(t < 20.) {
|
|
float phase = t/4.;
|
|
float phasePart = fract(phase);
|
|
float phaseSeq = mod(phase, 2.);
|
|
firePos = mix( mix(vec3(10., 9.5, 20.5), vec3(10., 9.5, -19.0), phasePart), mix(vec3(10., 9.5, -19.0), vec3(10., 9.5, 20.5), phasePart), step(1.0, phaseSeq));
|
|
} else if(t < 22.3) {
|
|
firePos = mix(vec3(14.5, 10., 7.5), vec3(-14.5, 10., 7.5), smoothstep(20., 22.3, t));
|
|
} else if(t < 24.3) {
|
|
firePos = mix(vec3(-14.5, 10., 7.5), vec3(14.5, 10., 7.5), smoothstep(22.3, 24.3, t));
|
|
} else {
|
|
firePos = mix(vec3(14.5, 9.5, -12.0), vec3(-15.0, 9.5, -12.0), smoothstep(24.3, 27.5, t));
|
|
}
|
|
|
|
q = p - firePos;
|
|
d = length(vec3(q.x, q.y, q.z))-0.15;
|
|
d += cos(q.x*15.+t*2.)*cos(q.y*12.)*cos(q.z*10.)*0.05;
|
|
res.xy = mix(vec2(d, 13.), res.xy, step(res.x, d));
|
|
res.zw = mix(vec2(d, 0.),res.zw, step(res.z, d));
|
|
|
|
return res;
|
|
}
|
|
|
|
vec2 dPortalA(vec3 p)
|
|
{
|
|
vec3 q = rotateY(p - portalA.pos, portalA.rotateY);
|
|
float d = dElipse(q, vec3(1.6, 2.6, 0.05), smoothstep(0., 0.15, t-portalA.time)*0.6);
|
|
return vec2(d, 1.);
|
|
}
|
|
|
|
vec2 dPortalB(vec3 p)
|
|
{
|
|
vec3 q = rotateY(p - portalB.pos, portalB.rotateY);
|
|
float d = dElipse(q, vec3(1.6, 2.6, 0.05), smoothstep(0., 0.15, t-portalB.time)*0.6);
|
|
return vec2(d, 2.);
|
|
}
|
|
|
|
vec4 map(vec3 p)
|
|
{
|
|
vec4 res = dBloomObjects(p);
|
|
vec2 res2 = dStructure(p);
|
|
if(res2.x < res.x) res.xy = res2.xy;
|
|
|
|
res2 = dWater(p);
|
|
if(res2.x < res.x) res.xy = res2.xy;
|
|
|
|
res2 = dPortalA(p);
|
|
if(res2.x < res.x) res.xy = res2.xy;
|
|
|
|
res2 = dPortalB(p);
|
|
if(res2.x < res.x) res.xy = res2.xy;
|
|
|
|
res2 = dPlatforms(p);
|
|
if(res2.x < res.x) res.xy = res2.xy;
|
|
|
|
return res;
|
|
}
|
|
|
|
vec4 intersect(vec3 o, vec3 rd, float tmin, float tmax)
|
|
{
|
|
float k = tmin;
|
|
vec4 res = vec4(tmax, -1, 999., 0.);
|
|
for(int i=0; i<120; ++i)
|
|
{
|
|
vec4 r = map(o + rd*k);
|
|
res.zw = mix(r.zw, res.zw, step(res.z, r.z));
|
|
if(r.x < 0.01)
|
|
{
|
|
res.x = k;
|
|
res.y = r.y;
|
|
break;
|
|
}
|
|
|
|
k+=r.x;
|
|
if(k > tmax)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
vec3 calcnormal(vec3 p)
|
|
{
|
|
vec2 e = vec2(0.001, 0.);
|
|
return normalize(
|
|
vec3(map(p+e.xyy).x-map(p-e.xyy).x,
|
|
map(p+e.yxy).x-map(p-e.yxy).x,
|
|
map(p+e.yyx).x-map(p-e.yyx).x)
|
|
);
|
|
}
|
|
|
|
#if APPLY_SHADOW == 1
|
|
float calcshadow(vec3 o, vec3 rd, float tmin, float tmax)
|
|
{
|
|
float k = tmin;
|
|
float shadow = 1.;
|
|
for(int i = 0; i < 20; ++i)
|
|
{
|
|
vec4 res = map(o + rd*k);
|
|
shadow = min(shadow, res.x*1.5);
|
|
|
|
k+=res.x;
|
|
|
|
if(k > tmax)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return shadow;
|
|
}
|
|
|
|
#endif
|
|
|
|
vec4 mapPortalColor(vec3 p, vec3 portalPos, float rotY, vec4 cristalcolor, vec4 fxcolor)
|
|
{
|
|
vec2 q = rotateY(p-portalPos, rotY).xy; q.y *= 0.55;
|
|
float d = length(q) - 1.4 + sin(q.x*10.+t*2.)*cos(q.y*10.+t*2.) * 0.05;
|
|
return mix(cristalcolor, fxcolor, smoothstep(-0.5, 0.2, d));
|
|
}
|
|
|
|
void calculatePosRayDirFromPortals(in PortalStruct portalO, in PortalStruct portalD, in vec3 p, in vec3 rd, out vec3 refpos, out vec3 refdir)
|
|
{
|
|
vec3 oRight = cross(vec3(0., 1., 0.), portalO.front);
|
|
vec3 oUp = cross(portalO.front, oRight);
|
|
|
|
vec3 dRight = cross(vec3(0., 1., 0.), portalD.front);
|
|
vec3 dUp = cross(portalD.front, dRight);
|
|
|
|
vec3 projRD=vec3(dot(oRight, rd), dot(oUp, rd), dot(portalO.front, rd));
|
|
vec3 localPos = p-portalO.pos;
|
|
vec3 projPos = vec3(dot(localPos, oRight), dot(localPos, oUp), dot(localPos, portalO.front));
|
|
|
|
refdir = normalize(-portalD.front*projRD.z + -dRight*projRD.x + dUp*projRD.y);
|
|
refpos = portalD.pos + -dRight*projPos.x + dUp*projPos.y + -portalD.front*projPos.z;
|
|
}
|
|
|
|
vec4 texcube( sampler2D sam, in vec3 p, in vec3 n )
|
|
{
|
|
vec4 x = texture( sam, p.yz );
|
|
vec4 y = texture( sam, p.zx );
|
|
vec4 z = texture( sam, p.xy );
|
|
return x*abs(n.x) + y*abs(n.y) + z*abs(n.z);
|
|
}
|
|
|
|
vec2 point2plane( in vec3 p, in vec3 n )
|
|
{
|
|
return p.zy*abs(n.x) + p.xz*abs(n.y) + p.xy*abs(n.z);
|
|
}
|
|
|
|
vec4 mapcolor(inout vec3 p, in vec4 res, inout vec3 normal, in vec3 rd, out vec3 refpos, out vec3 refdir, out vec4 lparams)
|
|
{
|
|
vec4 color = vec4(0.498, 0.584, 0.619, 1.0); lparams = vec4(1.0, 10., 0., 0.);
|
|
refdir = reflect(rd, normal); refpos = p;
|
|
|
|
if(res.y < 1.1) { // PortalA
|
|
color = mapPortalColor(p, portalA.pos, portalA.rotateY, vec4(1., 1., 1., 0.1), vec4(0.0, 0.35, 1.0, 1.));
|
|
calculatePosRayDirFromPortals(portalA, portalB, p, rd, refpos, refdir);
|
|
}
|
|
else if(res.y < 2.1) { // PortalB
|
|
color = mapPortalColor(p, portalB.pos, portalB.rotateY, vec4(0.0, 1., 1.0, 0.1), vec4(0.91, 0.46, 0.07, 1.));
|
|
calculatePosRayDirFromPortals(portalB, portalA, p, rd, refpos, refdir);
|
|
}
|
|
#if APPLY_COLORS == 1
|
|
else if(res.y < 3.1) { // Water
|
|
color = vec4(0.254, 0.239, 0.007, 1.0); lparams.xy = vec2(2.0, 50.);
|
|
color.rgb = mix(color.rgb, vec3(0.254, 0.023, 0.007), 1.-smoothstep(0.2, 1., fbm((p.xz+vec2(cos(t+p.x*2.)*0.2, cos(t+p.y*2.)*0.2))*0.5)));
|
|
color.rgb = mix(color.rgb, vec3(0.007, 0.254, 0.058), smoothstep(0.5, 1., fbm((p.xz*0.4+vec2(cos(t+p.x*2.)*0.2, cos(t+p.y*2.)*0.2))*0.5)));
|
|
}
|
|
else if(res.y < 4.1) { // Turbina
|
|
color = vec4(0.447, 0.490, 0.513, 1.0);
|
|
}
|
|
else if(res.y < 5.1) { //Window
|
|
color = vec4(0.662, 0.847, 0.898, 0.6); lparams=vec4(3., 5., 0., 0.9);
|
|
}
|
|
else if(res.y < 6.1) { // Metal tube
|
|
color = vec4(0.431, 0.482, 0.650, 0.6); lparams.xy=vec2(2., 5.);
|
|
}
|
|
else if(res.y < 7.1) {// Plastic
|
|
color = vec4(0.8, 0.8, 0.8, 1.); lparams.xy=vec2(0.5, 1.);
|
|
}
|
|
else if(res.y < 8.1) { //Railing
|
|
color = mix(vec4(1.), vec4(1., 1., 1., 0.), smoothstep(0.2, 0.21, fract(p.x)));
|
|
color = mix(vec4(1.), color, smoothstep(0.2, 0.21, fract(p.z)));
|
|
lparams.xy=vec2(1.0, 1.); refdir = rd;
|
|
}
|
|
else if(res.y < 9.1) { // Reflectance -> can be plastic
|
|
color = vec4(1., 1., 1., 0.1); lparams.xy=vec2(1.0, 10.);
|
|
}
|
|
else if(res.y < 10.1) { // Exit
|
|
vec3 q = p - vec3(1.5, 11.0, -31.);
|
|
color = vec4(0.6, 0.6, 0.6, 0.65);
|
|
color.rgb = mix(vec3(0.749, 0.898, 0.909), color.rgb, smoothstep(2., 10., length(q.xy)));
|
|
color.rgb += mix(vec3(0.1), vec3(0.), smoothstep(2., 5., length(q.xy)));
|
|
|
|
vec3 q2 = q;
|
|
vec2 c = vec2(2., 1.5);
|
|
float velsign = mix(-1., 1., step(0.5, fract(q2.y*0.5)));
|
|
q2.x = mod(velsign*t+q2.x+cos(q2.y*3.)*0.5, 1.8);
|
|
q2.y = mod(q2.y, 1.15);
|
|
float d = max(abs(q2.x)-0.9, abs(q2.y)-0.1);
|
|
color.rgb += mix(vec3(0.286, 0.941, 0.992)*1.6, vec3(0.), smoothstep(-0.1, 0.1, d));
|
|
|
|
vec3 localp = p - vec3(1.5, 11.0, -31.);
|
|
refpos = vec3(1.5, 11.0, 28.0) + localp;
|
|
lparams=vec4(1.0, 10., 0., 0.1); refdir = rd;
|
|
}
|
|
else if(res.y < 11.1) { // Exit border
|
|
vec3 q = p; q.z = abs(q.z); q = q - vec3(0.0, 9.5, 31.);
|
|
color = vec4(0.8, 0.8, 0.8, 1.);
|
|
float d =length(abs(q.x+cos(q.y*0.5)*0.6 -3.0))-0.06;
|
|
d = min(d, length(abs(q.x+cos(PI+q.y*0.5)*0.6 +3.0))-0.06);
|
|
color.rgb = mix(vec3(0.286, 0.941, 0.992), color.rgb, smoothstep(0., 0.01, d));
|
|
lparams = mix(vec4(0., 0., 0., 1.), lparams, smoothstep(0., 0.2, d));
|
|
}
|
|
else if(res.y < 12.1) { // Fireball base
|
|
vec3 q = p - vec3(10., 9.5, 26.5);
|
|
color = vec4(1.0, 1.0, 1.0, 1.);
|
|
float d = length(q-vec3(0., 0., -2.5)) - 2.0;
|
|
color = mix(vec4(0.976, 0.423, 0.262, 1.), color, smoothstep(-2., 0.01, d));
|
|
}
|
|
else if(res.y < 13.1) { // Fireball
|
|
color = vec4(1., 0.0, 0.0, 1.0);
|
|
color.rgb = mix(color.rgb, vec3(0.75, 0.94, 0.28), smoothstep(26.5, 27.0, t));
|
|
}
|
|
|
|
else if(res.y > 19. && res.y < 25.) { // Walls
|
|
|
|
float rand = fbm(point2plane(p, normal));
|
|
vec3 col = vec3(0.498, 0.584, 0.619);
|
|
color = vec4(vec3(col), 1.0);
|
|
color = mix(color, vec4(col*0.75, 1.0), smoothstep(0.2, 1.0, rand));
|
|
color = mix(color, vec4(col*0.80, 1.0), smoothstep(0.4, 1.0, fbm(point2plane(p*1.5, normal))));
|
|
color = mix(color, vec4(col*0.7, 1.0), smoothstep(0.6, 1.0, fbm(point2plane(p*4.5, normal))));
|
|
|
|
vec3 dirtcolor = mix(vec3(0., 0., 0.), vec3(0.403, 0.380, 0.274)*0.2, rand);
|
|
float dirtheight = 0.1+rand*1.0;
|
|
dirtcolor = mix(dirtcolor, vec3(0.243, 0.223, 0.137), smoothstep(dirtheight, dirtheight + 0.5, p.y));
|
|
dirtheight = rand*2.;
|
|
color.rgb = mix(dirtcolor, color.rgb, smoothstep(dirtheight, dirtheight+2.0, p.y));
|
|
|
|
#ifdef TEXTURE
|
|
vec4 noise = mix(vec4(0.), texture(iChannel0, point2plane(p*0.037, normal)) * 0.2, smoothstep(0.2, 1., rand));
|
|
#else
|
|
vec4 noise = vec4(0.0, 0.0, 0.0, 0.0);
|
|
#endif
|
|
normal = normalize(normal + vec3(noise.x, 0., noise.z));
|
|
refdir = normalize(reflect(rd, normal));
|
|
|
|
if(res.y < 20.1) { // BROWN_WALL_BLOCK
|
|
float d = -(p.x-6.1);
|
|
d = max(d, p.y-12.6); d = min(d, p.y-6.5);
|
|
color *= mix(vec4(1.), vec4(0.227, 0.137, 0.011, 1.0), smoothstep(0.0, 0.1, d));
|
|
}
|
|
else if(res.y < 21.1) { // WHITE_PLATFORM_BLOCK
|
|
color *= vec4(0.529, 0.572, 0.709, 1.0);
|
|
vec3 q = p - vec3(11.5, 6.85, 7.0);
|
|
float d = abs(q.y)-0.05;
|
|
color.rgb = mix(vec3(0.945, 0.631, 0.015), color.rgb, smoothstep(0., 0.01, d));
|
|
lparams.w = mix(1., 0., smoothstep(0., 0.2, d));
|
|
}
|
|
else if(res.y < 22.1) { // TRANSPARENT_PLATFORM_BLOCK
|
|
color *= vec4(0.431, 0.482, 0.650, 0.1);
|
|
refdir = rd; lparams.xy=vec2(2., 5.);
|
|
}
|
|
else if(res.y < 23.1) { // CEILING_BLOCK
|
|
color *= mix(vec4(0.227, 0.137, 0.011, 1.0), vec4(1.), smoothstep(0., 0.01, p.z+6.));
|
|
}
|
|
}
|
|
#endif
|
|
return color;
|
|
}
|
|
|
|
void initLights()
|
|
{
|
|
vec3 col = vec3(0.925, 0.968, 0.972);
|
|
|
|
ambientcolor = col;
|
|
|
|
// Center Up
|
|
lights[0].pos = vec3(0., 13.0, 0.);
|
|
lights[0].color = col*0.25;
|
|
|
|
// Window
|
|
lights[1].pos = vec3(14.0, 15.5, -12.0);
|
|
lights[1].color = col*0.25;
|
|
|
|
lights[2].pos = vec3(14.0, 15.5, -6.0);
|
|
lights[2].color = col*0.25;
|
|
}
|
|
|
|
void initPortals()
|
|
{
|
|
portalsA[0].pos = vec3(-140.5, 10., 23.0); portalsA[0].front = vec3(1., 0., 0.); portalsA[0].rotateY = PI*0.5; portalsA[0].time = 0.;
|
|
portalsA[1].pos = vec3(-14.5, 10., 23.0); portalsA[1].front = vec3(1., 0., 0.); portalsA[1].rotateY = PI*0.5; portalsA[1].time = 6.0;
|
|
portalsA[2].pos = vec3(-14.5, 10., -2.5); portalsA[2].front = vec3(1., 0., 0.); portalsA[2].rotateY = PI*0.5; portalsA[2].time = 13.5;
|
|
portalsA[3].pos = vec3(10.5, 9.6, -20.5); portalsA[3].front = vec3(0., 0., 1.); portalsA[3].rotateY = 0.; portalsA[3].time = 18.;
|
|
portalsA[4].pos = vec3(14.5, 9.5, -12.0); portalsA[4].front = vec3(-1., 0., 0.); portalsA[4].rotateY = PI*0.5; portalsA[4].time = 23.5;
|
|
|
|
portalA = portalsA[0];
|
|
|
|
portalB.pos = vec3(14.5, 10., 7.5);
|
|
portalB.front = vec3(-1., 0., 0.);
|
|
portalB.rotateY = -PI*0.5; portalB.time = 0.;
|
|
}
|
|
|
|
void initState()
|
|
{
|
|
states[0].posStart = vec3(0., 11.0, 26.0); states[0].posEnd = vec3(0., 11.0, 26.0); states[0].duration = 0.; states[0].lerptime = 0.; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
states[1].posStart = vec3(0., 11.0, 26.0); states[1].posEnd = vec3(0., 11.0, 23.0); states[1].duration = 6.75; states[1].lerptime = 0.5; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
states[2].posStart = vec3(0., 11.0, 23.0); states[2].posEnd = vec3(-12.6, 11.0, 23.0); states[2].duration = 4.0; states[2].lerptime = 1.0; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
|
|
// Go to Portal B
|
|
states[3].posStart = vec3(-12.6, 11.0, 23.0); states[3].posEnd = vec3(-14.5, 11., 23.0); states[3].duration = 0.1; states[3].lerptime = 0.1; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
states[4].posStart = vec3(14.5, 11., 7.5); states[4].posEnd = vec3(13.5, 11., 7.5); states[4].duration = 3.0; states[4].lerptime = 0.5; states[0].isEnterTime = 1.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
|
|
// Go to Portal A
|
|
states[5].posStart = vec3(13.5, 11., 7.5); states[5].posEnd = vec3(14.5, 11., 7.5); states[5].duration = 0.1; states[5].lerptime = 1.25; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
states[6].posStart = vec3(-14.5, 11., -2.5); states[6].posEnd = vec3(-11.6, 11., -2.5); states[6].duration = 15.; states[6].lerptime = 1.0; states[0].isEnterTime = 1.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
|
|
states[7].posStart = vec3(-11.6, 11., -2.5); states[7].posEnd = vec3(-11.6, 11., -23.0); states[7].duration = 7.5; states[7].lerptime = 7.0; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
states[8].posStart = vec3(-11.6, 11., -23.0); states[8].posEnd = vec3(0.5, 11., -23.0); states[8].duration = 3.0; states[8].lerptime = 2.5; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
states[9].posStart = vec3(0.5, 11., -23.0); states[9].posEnd = vec3(0.5, 11., -28.0); states[9].duration = 10.; states[9].lerptime = 0.5; states[0].isEnterTime = 0.; states[0].enterPortal = 0.; states[0].exitPortal = 1.;
|
|
|
|
t = mod(t, 40.);
|
|
}
|
|
|
|
void initOrientations()
|
|
{
|
|
orientations[0].orientation = vec3(0., 0., -1.); orientations[0].lerptime = 0.; orientations[0].duration = 0.;
|
|
orientations[1].orientation = vec3(0., 0., -1.); orientations[1].lerptime = 0.0; orientations[1].duration = 1.0;
|
|
orientations[2].orientation = normalize(vec3(0.1, 0.25, -0.5)); orientations[2].lerptime = 1.50; orientations[2].duration = 2.0;
|
|
orientations[3].orientation = normalize(vec3(1., 0., -1.5)); orientations[3].lerptime = 0.75; orientations[3].duration = 2.0;
|
|
orientations[4].orientation = vec3(0., 0., -1.); orientations[4].lerptime = 1.25; orientations[4].duration = 1.25;
|
|
orientations[4].orientation = vec3(-1., 0., 0.); orientations[4].lerptime = 1.0; orientations[4].duration = 6.25;
|
|
orientations[5].orientation = vec3(0., 0., -1.); orientations[5].lerptime = 0.75; orientations[5].duration = 1.25;
|
|
orientations[6].orientation = vec3(-1., 0., -0.4); orientations[6].lerptime = 0.60; orientations[6].duration = 3.25;
|
|
orientations[7].orientation = vec3(0., 0., 1.); orientations[7].lerptime = 0.75; orientations[7].duration = 0.75;
|
|
orientations[8].orientation = vec3(1., 0., -0.65); orientations[8].lerptime = 0.75; orientations[8].duration = 3.8;
|
|
orientations[9].orientation = vec3(0.0, 0., 1.); orientations[9].lerptime = 1.0; orientations[9].duration = 1.5;
|
|
orientations[10].orientation = vec3(1.0, 0., -0.2); orientations[10].lerptime = 0.75; orientations[10].duration = 3.2;
|
|
orientations[11].orientation = vec3(-0.2, 0., -1.); orientations[11].lerptime = 2.0; orientations[11].duration = 5.0;
|
|
orientations[12].orientation = normalize(vec3(0.6, -0.5, -1.)); orientations[12].lerptime = 0.5; orientations[12].duration = 5.0;
|
|
orientations[13].orientation = vec3(1., 0., 0.); orientations[13].lerptime = 0.5; orientations[13].duration = 3.5;
|
|
orientations[14].orientation = vec3(0., 0., -1.); orientations[14].lerptime = 0.5; orientations[14].duration = 10.0;
|
|
|
|
orientation = orientations[0].orientation;
|
|
}
|
|
|
|
vec3 modOrientationToPortals(vec3 or, vec3 enterFront, vec3 exitFront)
|
|
{
|
|
vec3 enterRight = cross(vec3(0., 1., 0.), enterFront);
|
|
vec3 enterUp = cross(enterFront, enterRight);
|
|
|
|
vec3 exitRight = cross(vec3(0., 1., 0.), exitFront);
|
|
vec3 exitUp = cross(exitFront, exitRight);
|
|
|
|
vec3 enterProjection = vec3
|
|
(
|
|
dot(or, enterRight),
|
|
dot(or, enterUp),
|
|
dot(or, enterFront)
|
|
);
|
|
|
|
return exitFront*enterProjection.z + exitRight*enterProjection.x + exitUp*enterProjection.y;
|
|
}
|
|
|
|
void updateState()
|
|
{
|
|
vec3 axisEnterFront = vec3(0., 0., -1.);
|
|
vec3 axisExitFront = vec3(0., 0., -1.);
|
|
float portalEnterTime = 0.;
|
|
float at = 0.;
|
|
position = vec3(-5., 11.0, 26.);
|
|
|
|
for(int i = 4; i >= 0; i--) { // Set current Portal
|
|
if(t > portalsA[i].time) {
|
|
portalA = portalsA[i];
|
|
break;
|
|
}
|
|
}
|
|
for(int i = 1; i < 10; ++i) { // Set Camera position
|
|
at += states[i].duration;
|
|
portalEnterTime = mix(portalEnterTime, at-states[i].duration, step(0.5, states[i].isEnterTime));
|
|
|
|
vec3 axisEnterFrontA = -mix(portalA.front, portalB.front, step(0.5, states[i].enterPortal));
|
|
axisEnterFront = mix(axisEnterFront, axisEnterFrontA, step(0.5, states[i].isEnterTime));
|
|
|
|
vec3 axisExitFrontA = mix(portalA.front, portalB.front, step(0.5, states[i].exitPortal));
|
|
axisExitFront = mix(axisExitFront, axisExitFrontA, step(0.5, states[i].isEnterTime));
|
|
if(t < at) {
|
|
position = mix(states[i].posStart, states[i].posEnd, clamp((t - (at-states[i].duration)) / (states[i].lerptime), 0., 1.));
|
|
break;
|
|
}
|
|
}
|
|
at = 0.;
|
|
for(int i = 1; i < 15; ++i) { // Set Camera orientation
|
|
at += orientations[i].duration;
|
|
if(t < at) {
|
|
vec3 prevOrientation = mix(modOrientationToPortals(orientations[i-1].orientation, axisEnterFront, axisExitFront), orientations[i-1].orientation, step(portalEnterTime, at-orientations[i].duration-orientations[i-1].duration));
|
|
vec3 currentOrientation = mix(modOrientationToPortals(orientations[i].orientation, axisEnterFront, axisExitFront), orientations[i].orientation, step(portalEnterTime, at-orientations[i].duration));
|
|
orientation = normalize(mix(prevOrientation, currentOrientation, clamp((t - (at-orientations[i].duration)) / (orientations[i].lerptime), 0., 1.)));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
|
{
|
|
t = iGlobalTime;
|
|
|
|
initState();
|
|
initPortals();
|
|
initOrientations();
|
|
initLights();
|
|
|
|
updateState();
|
|
|
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
|
vec2 p = (uv * 2. -1.) * vec2(iResolution.x/iResolution.y, 1.);
|
|
#ifdef MOUSE
|
|
vec2 mo = mix(vec2(0.), iMouse.xy / iResolution.xy, step(0.001, length(iMouse.zw)));
|
|
#else
|
|
vec2 mo = mix(vec2(0.), 0.0 / iResolution.xy, step(0.001, length(0.0)));
|
|
#endif
|
|
|
|
vec3 right = cross(vec3(0., 1., 0.), orientation);
|
|
orientation += right*mo.x + vec3(0., 1., 0)*mo.y;
|
|
|
|
vec3 ww = normalize(orientation);
|
|
vec3 uu = normalize(cross(vec3(0., 1., 0.), ww));
|
|
vec3 vv = normalize(cross(ww, uu));
|
|
|
|
vec3 rd = normalize(p.x*uu*0.7 + p.y*vv + 1.*ww);
|
|
|
|
float fov = tan(0.46);
|
|
rd = normalize(p.x*uu*fov + p.y*vv*fov + 1.*ww);
|
|
vec3 color = vec3(0.);
|
|
float att = 1.;
|
|
for(int i = 0; i < 3; ++i)
|
|
{
|
|
vec4 res = intersect(position, rd, 0.40, 9999.);
|
|
if(res.y > 0.0)
|
|
{
|
|
vec3 point = position + rd*res.x;
|
|
|
|
vec3 normal = calcnormal(point);
|
|
vec3 refposition;
|
|
vec3 refdir;
|
|
vec4 lparams;
|
|
vec4 colorrgba = mapcolor(point, res, normal, rd, refposition, refdir, lparams);
|
|
|
|
float latt = 1.-ambient;
|
|
vec3 acolor = colorrgba.rgb*ambientcolor*ambient;
|
|
for(int lidx = 0; lidx < 3; ++lidx)
|
|
{
|
|
vec3 ldir = lights[lidx].pos - point;
|
|
float ldirLength = length(ldir);
|
|
ldir /= ldirLength;
|
|
latt *= 1.-clamp((ldirLength-5.)/35., 0., 1.);
|
|
|
|
vec3 diffuse = colorrgba.rgb;
|
|
float diffactor = max(0., pow(dot(ldir, normal), 1.0))*latt;
|
|
|
|
vec3 reflec = reflect(rd, normal);
|
|
float specfactor = pow(max(0., dot(ldir, reflec)), lparams.y) * lparams.x;
|
|
|
|
float shadow = 1.;
|
|
#if APPLY_SHADOW == 1
|
|
shadow = max(calcshadow(point, ldir, 0.8, ldirLength), 0.01);
|
|
#endif
|
|
|
|
acolor += diffuse * diffactor * lights[lidx].color* shadow;
|
|
acolor += specfactor * lights[lidx].color* shadow;
|
|
color += (acolor*colorrgba.a*att);
|
|
}
|
|
|
|
color = lparams.w*colorrgba.rgb + (1.-lparams.w)*color.rgb;;
|
|
vec3 fireballcolor = mix(vec3(0.91, 0.46, 0.07), vec3(0.42, 0.90, 0.00), smoothstep(26.5, 27.0, t));
|
|
vec3 bloomcolor = mix(fireballcolor, vec3(1.6, 1.65, 1.65), step(0.5, res.w));
|
|
color.rgb = mix(mix(bloomcolor, color.rgb, 0.5), color.rgb, smoothstep(0., 1.0, res.z));
|
|
|
|
att = max(att*(1.-colorrgba.a), 0.);
|
|
if(att < 0.01)
|
|
{
|
|
break;
|
|
}
|
|
|
|
rd = refdir;
|
|
position = refposition;
|
|
}
|
|
else
|
|
{
|
|
att = 0.;
|
|
break;
|
|
}
|
|
}
|
|
|
|
float fadeFactor = mix(0., 1., smoothstep(39., 40., t));
|
|
fadeFactor = mix(1., fadeFactor, smoothstep(0., 1., t));
|
|
|
|
fragColor = mix(vec4(color, 1.), vec4(0.), fadeFactor);
|
|
}
|
|
|
|
void main(void)
|
|
{
|
|
//just some shit to wrap shadertoy's stuff
|
|
vec2 FragCoord = vTexCoord.xy*global.OutputSize.xy;
|
|
FragCoord.y = -FragCoord.y;
|
|
mainImage(FragColor,FragCoord);
|
|
}
|