mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-25 00:51:29 +11:00
Add plethora of new shaders from shadertoy
This commit is contained in:
parent
7155843594
commit
06da9fcac8
286
procedural/fizzer-kirby-jump.slang
Normal file
286
procedural/fizzer-kirby-jump.slang
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
#version 450
|
||||||
|
//kirby jump
|
||||||
|
// fizzer 2018-01-31
|
||||||
|
// https://www.shadertoy.com/view/lt2fD3
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// polynomial smooth min (from IQ)
|
||||||
|
float smin( float a, float b, float k )
|
||||||
|
{
|
||||||
|
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
|
||||||
|
return mix( b, a, h ) - k*h*(1.0-h);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float smax(float a,float b, float k)
|
||||||
|
{
|
||||||
|
return -smin(-a,-b,k);
|
||||||
|
}
|
||||||
|
|
||||||
|
mat2 rotmat(float a)
|
||||||
|
{
|
||||||
|
return mat2(cos(a),sin(a),-sin(a),cos(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
float shoesDist(vec3 p)
|
||||||
|
{
|
||||||
|
vec3 op=p;
|
||||||
|
float d=1e4;
|
||||||
|
|
||||||
|
p.y-=1.5;
|
||||||
|
|
||||||
|
// right shoe
|
||||||
|
op=p;
|
||||||
|
p-=vec3(-.5,-.6,-.9);
|
||||||
|
p.yz=rotmat(-.7)*p.yz;
|
||||||
|
p.xz=rotmat(0.1)*p.xz;
|
||||||
|
d=min(d,-smin(p.y,-(length(p*vec3(1.6,1,1))-.64),.2));
|
||||||
|
p=op;
|
||||||
|
|
||||||
|
// left shoe
|
||||||
|
op=p;
|
||||||
|
p-=vec3(.55,-.8,0.4);
|
||||||
|
p.x=-p.x;
|
||||||
|
p.yz=rotmat(1.4)*p.yz;
|
||||||
|
d=min(d,-smin(p.y,-(length(p*vec3(1.6,1,1))-.73),.2));
|
||||||
|
p=op;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sceneDist(vec3 p)
|
||||||
|
{
|
||||||
|
vec3 op=p;
|
||||||
|
float d=shoesDist(p);
|
||||||
|
|
||||||
|
d=min(d,p.y);
|
||||||
|
p.y-=1.5;
|
||||||
|
|
||||||
|
// torso
|
||||||
|
d=min(d,length(p)-1.);
|
||||||
|
|
||||||
|
|
||||||
|
// left arm
|
||||||
|
op=p;
|
||||||
|
p-=vec3(.66,.7,0);
|
||||||
|
p.xz=rotmat(-0.1)*p.xz;
|
||||||
|
d=smin(d,(length(p*vec3(1.8,1,1))-.58),.07);
|
||||||
|
p=op;
|
||||||
|
|
||||||
|
// right arm
|
||||||
|
op=p;
|
||||||
|
p-=vec3(-.75,0.2,0);
|
||||||
|
d=smin(d,(length(p*vec3(1,1.5,1))-.54),.03);
|
||||||
|
p=op;
|
||||||
|
|
||||||
|
// mouth
|
||||||
|
p.y-=.11;
|
||||||
|
float md=smax(p.z+.84,smax(smax(p.x-.2,p.y-.075,.2),dot(p,vec3(.7071,-.7071,0))-.1,.08),.04);
|
||||||
|
p.x=-p.x;
|
||||||
|
md=smax(md,smax(p.z+.84,smax(smax(p.x-.2,p.y-.075,.2),dot(p,vec3(.7071,-.7071,0))-.1,.08),.01),.13);
|
||||||
|
d=smax(d,-md,.012);
|
||||||
|
|
||||||
|
// tongue
|
||||||
|
p=op;
|
||||||
|
d=smin(d,length((p-vec3(0,.03,-.75))*vec3(1,1,1))-.16,.01);
|
||||||
|
|
||||||
|
return min(d,10.);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vec3 sceneNorm(vec3 p)
|
||||||
|
{
|
||||||
|
vec3 e=vec3(1e-3,0,0);
|
||||||
|
float d = sceneDist(p);
|
||||||
|
return normalize(vec3(sceneDist(p + e.xyy) - sceneDist(p - e.xyy), sceneDist(p + e.yxy) - sceneDist(p - e.yxy),
|
||||||
|
sceneDist(p + e.yyx) - sceneDist(p - e.yyx)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// from simon green and others
|
||||||
|
float ambientOcclusion(vec3 p, vec3 n)
|
||||||
|
{
|
||||||
|
const int steps = 4;
|
||||||
|
const float delta = 0.15;
|
||||||
|
|
||||||
|
float a = 0.0;
|
||||||
|
float weight = 4.;
|
||||||
|
for(int i=1; i<=steps; i++) {
|
||||||
|
float d = (float(i) / float(steps)) * delta;
|
||||||
|
a += weight*(d - sceneDist(p + n*d));
|
||||||
|
weight *= 0.5;
|
||||||
|
}
|
||||||
|
return clamp(1.0 - a, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// a re-shaped cosine, to make the peaks more pointy
|
||||||
|
float cos2(float x){return cos(x-sin(x)/3.);}
|
||||||
|
|
||||||
|
float starShape(vec2 p)
|
||||||
|
{
|
||||||
|
float a=atan(p.y,p.x)+iGlobalTime/3.;
|
||||||
|
float l=pow(length(p),.8);
|
||||||
|
float star=1.-smoothstep(0.,(3.-cos2(a*5.*2.))*.02,l-.5+cos2(a*5.)*.1);
|
||||||
|
return star;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
// Normalized pixel coordinates (from 0 to 1)
|
||||||
|
vec2 uv = fragCoord/iResolution.xy;
|
||||||
|
|
||||||
|
float an=cos(iGlobalTime)*.1;
|
||||||
|
|
||||||
|
vec2 ot=uv*2.-1.;
|
||||||
|
ot.y*=iResolution.y/iResolution.x;
|
||||||
|
vec3 ro=vec3(0.,1.4,4.);
|
||||||
|
vec3 rd=normalize(vec3(ot.xy,-1.3));
|
||||||
|
|
||||||
|
rd.xz=mat2(cos(an),sin(an),sin(an),-cos(an))*rd.xz;
|
||||||
|
ro.xz=mat2(cos(an),sin(an),sin(an),-cos(an))*ro.xz;
|
||||||
|
|
||||||
|
float s=20.;
|
||||||
|
|
||||||
|
// primary ray
|
||||||
|
float t=0.,d=0.;
|
||||||
|
for(int i=0;i<80;++i)
|
||||||
|
{
|
||||||
|
d=sceneDist(ro+rd*t);
|
||||||
|
if(d<1e-4)
|
||||||
|
break;
|
||||||
|
if(t>10.)
|
||||||
|
break;
|
||||||
|
t+=d*.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
t=min(t,10.0);
|
||||||
|
|
||||||
|
// shadow ray
|
||||||
|
vec3 rp=ro+rd*t;
|
||||||
|
vec3 n=sceneNorm(rp);
|
||||||
|
float st=5e-3;
|
||||||
|
vec3 ld=normalize(vec3(2,4,-4));
|
||||||
|
for(int i=0;i<20;++i)
|
||||||
|
{
|
||||||
|
d=sceneDist(rp+ld*st);
|
||||||
|
if(d<1e-5)
|
||||||
|
break;
|
||||||
|
if(st>5.)
|
||||||
|
break;
|
||||||
|
st+=d*2.;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ambient occlusion and shadowing
|
||||||
|
vec3 ao=vec3(ambientOcclusion(rp, n));
|
||||||
|
float shad=mix(.85,1.,step(5.,st));
|
||||||
|
|
||||||
|
ao*=mix(.3,1.,.5+.5*n.y);
|
||||||
|
|
||||||
|
// soft floor shadow
|
||||||
|
if(rp.y<1e-3)
|
||||||
|
ao*=mix(mix(vec3(1,.5,.7),vec3(1),.4)*.6,vec3(1),smoothstep(0.,1.6,length(rp.xz)));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vec3 diff=vec3(1);
|
||||||
|
vec3 emit=vec3(0);
|
||||||
|
|
||||||
|
// skin
|
||||||
|
diff*=vec3(1.15,.3,.41)*1.4;
|
||||||
|
diff+=.4*mix(1.,0.,smoothstep(0.,1.,length(rp.xy-vec2(0.,1.9))));
|
||||||
|
diff+=.5*mix(1.,0.,smoothstep(0.,.5,length(rp.xy-vec2(.7,2.5))));
|
||||||
|
diff+=.36*mix(1.,0.,smoothstep(0.,.5,length(rp.xy-vec2(-1.1,1.8))));
|
||||||
|
|
||||||
|
if(rp.y<1e-3)
|
||||||
|
diff=vec3(.6,1,.6);
|
||||||
|
|
||||||
|
// mouth
|
||||||
|
diff*=mix(vec3(1,.3,.2),vec3(1),smoothstep(.97,.99,length(rp-vec3(0,1.5,0))));
|
||||||
|
|
||||||
|
// shoes
|
||||||
|
diff=mix(vec3(1.,.05,.1),diff,smoothstep(0.,0.01,shoesDist(rp)));
|
||||||
|
diff+=.2*mix(1.,0.,smoothstep(0.,.2,length(rp.xy-vec2(-0.5,1.4))));
|
||||||
|
diff+=.12*mix(1.,0.,smoothstep(0.,.25,length(rp.xy-vec2(0.57,.3))));
|
||||||
|
|
||||||
|
// bounce light from the floor
|
||||||
|
diff+=vec3(.25,1.,.25)*smoothstep(-.3,1.7,-rp.y+1.)*max(0.,-n.y)*.7;
|
||||||
|
|
||||||
|
vec3 orp=rp;
|
||||||
|
rp.y-=1.5;
|
||||||
|
rp.x=abs(rp.x);
|
||||||
|
|
||||||
|
// blushes
|
||||||
|
diff*=mix(vec3(1,.5,.5),vec3(1),smoothstep(.1,.15,length((rp.xy-vec2(.4,.2))*vec2(1,1.65))));
|
||||||
|
|
||||||
|
rp.xy-=vec2(.16,.45);
|
||||||
|
rp.xy*=.9;
|
||||||
|
orp=rp;
|
||||||
|
rp.y=pow(abs(rp.y),1.4)*sign(rp.y);
|
||||||
|
|
||||||
|
// eye outline
|
||||||
|
diff*=smoothstep(.058,.067,length((rp.xy)*vec2(.9,.52)));
|
||||||
|
|
||||||
|
rp=orp;
|
||||||
|
rp.y+=.08;
|
||||||
|
rp.y-=pow(abs(rp.x),2.)*16.;
|
||||||
|
|
||||||
|
// eye reflections
|
||||||
|
emit+=vec3(.1,.5,1.)*(1.-smoothstep(.03,.036,length((rp.xy)*vec2(.7,.3))))*max(0.,-rp.y)*10.;
|
||||||
|
|
||||||
|
rp=orp;
|
||||||
|
rp.y-=.12;
|
||||||
|
|
||||||
|
// eye highlights
|
||||||
|
emit+=vec3(1)*(1.-smoothstep(.03,.04,length((rp.xy)*vec2(1.,.48))));
|
||||||
|
|
||||||
|
// fresnel
|
||||||
|
diff+=pow(clamp(1.-dot(-rd,n),0.,.9),4.)*.5;
|
||||||
|
|
||||||
|
// background and floor fade
|
||||||
|
vec3 backg=vec3(1.15,.3,.41)*.9;
|
||||||
|
ot.x+=.6+iGlobalTime/50.;
|
||||||
|
ot.y+=cos(floor(ot.x*2.)*3.)*.1+.2;
|
||||||
|
ot.x=mod(ot.x,.5)-.25;
|
||||||
|
backg=mix(backg,vec3(1.,1.,.5),.1*starShape((ot-vec2(0.,.6))*8.)*smoothstep(9.,10.,t));
|
||||||
|
diff=mix(diff,backg,smoothstep(.9,10.,t));
|
||||||
|
|
||||||
|
fragColor.rgb=mix(vec3(.15,0,0),vec3(1),ao)*shad*diff*1.1;
|
||||||
|
fragColor.rgb+=emit;
|
||||||
|
fragColor.a = 1.0f;
|
||||||
|
|
||||||
|
fragColor.rgb=pow(fragColor.rgb,vec3(1./2.4));
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
80
procedural/fizzer-power-coils.slang
Normal file
80
procedural/fizzer-power-coils.slang
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#version 450
|
||||||
|
#
|
||||||
|
//Playing with inversion and volumetric light.
|
||||||
|
//fizer 2015-06-06
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
void mainImage(out vec4 c, vec2 q)
|
||||||
|
{
|
||||||
|
float a=iGlobalTime*.1+1.,b=.5,g,e,t=0.,s;
|
||||||
|
vec3 r=vec3(0.,0.,3.),w=normalize(vec3((q-iResolution.xy/2.)/iResolution.y,-.5)),p;
|
||||||
|
|
||||||
|
mat2 x=mat2(cos(a),sin(a),sin(a),-cos(a)),y=mat2(cos(b),sin(b),sin(b),-cos(b));
|
||||||
|
|
||||||
|
w.xz=y*w.xz;
|
||||||
|
r.xz=y*r.xz;
|
||||||
|
|
||||||
|
w.yz=x*w.yz;
|
||||||
|
r.yz=x*r.yz;
|
||||||
|
|
||||||
|
c.rgb=vec3(0.,0.,.02);
|
||||||
|
|
||||||
|
for(int i=0;i<150;++i)
|
||||||
|
{
|
||||||
|
p=r+w*t;
|
||||||
|
|
||||||
|
float f=.25,d=1e4;
|
||||||
|
for(int j=0;j<2;++j)
|
||||||
|
{
|
||||||
|
s=.2*dot(p,p);
|
||||||
|
p=p/s;
|
||||||
|
f*=s;
|
||||||
|
g=p.z;
|
||||||
|
e=atan(p.y,p.x);
|
||||||
|
p=(mod(p,2.)-1.)*1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
d=min((length(abs(p.xy)-1.3)-.1)*f,1e2);
|
||||||
|
|
||||||
|
if(d<1e-3)
|
||||||
|
break;
|
||||||
|
|
||||||
|
c.rgb+=vec3(.3,.4,.8)*(pow(.5+.5*cos(g*.5+a*77.+cos(e*10.)),16.))*
|
||||||
|
(1.-smoothstep(0.,1.,70.*d))*.25;
|
||||||
|
|
||||||
|
t+=d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
433
procedural/fizzer-the-popular-shader.slang
Normal file
433
procedural/fizzer-the-popular-shader.slang
Normal file
|
@ -0,0 +1,433 @@
|
||||||
|
#version 450
|
||||||
|
#
|
||||||
|
//I remade my other shader (https://www.shadertoy.com/view/ldjGWD) inspired by "The Popular Demo", to make it more accurate
|
||||||
|
//I added a tiling effect to make the robot look faceted, but it seems to somehow over-complicate the shader so it doesn't compile.
|
||||||
|
// fizzer - 2014-01-04
|
||||||
|
|
||||||
|
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 USE_IQ_SMIN 0
|
||||||
|
|
||||||
|
float time;
|
||||||
|
|
||||||
|
vec2 leg0[3];
|
||||||
|
vec2 leg1[3];
|
||||||
|
|
||||||
|
vec2 arm0[3];
|
||||||
|
vec2 arm1[3];
|
||||||
|
|
||||||
|
float wlen=15.0;
|
||||||
|
float bob;
|
||||||
|
float wc_scale=0.5;
|
||||||
|
float scroll;
|
||||||
|
float scene_scale=15.0;
|
||||||
|
|
||||||
|
// Finds the entry and exit points of a 2D ray with a circle of radius 1
|
||||||
|
// centered at the origin.
|
||||||
|
vec2 intersectCircle(vec2 ro, vec2 rd)
|
||||||
|
{
|
||||||
|
float a = dot(rd, rd);
|
||||||
|
float b = 2.0 * dot(rd, ro);
|
||||||
|
float ds = b * b - 4.0 * a * (dot(ro, ro) - 1.0);
|
||||||
|
|
||||||
|
if(ds < 0.0)
|
||||||
|
return vec2(1e3);
|
||||||
|
|
||||||
|
return ((-b - sqrt(ds) * vec2(-1.0, 1.0))) / (2.0 * a);
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 rotateXMat(float a)
|
||||||
|
{
|
||||||
|
return mat3(1.0, 0.0, 0.0, 0.0, cos(a), -sin(a), 0.0, sin(a), cos(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 rotateYMat(float a)
|
||||||
|
{
|
||||||
|
return mat3(cos(a), 0.0, -sin(a), 0.0, 1.0, 0.0, sin(a), 0.0, cos(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapted from https://www.shadertoy.com/view/ldlGR7
|
||||||
|
vec2 solve( vec2 p, float l1, float l2, float side )
|
||||||
|
{
|
||||||
|
vec2 q = p*( 0.5 + 0.5*(l1*l1-l2*l2)/dot(p,p) );
|
||||||
|
|
||||||
|
float s = l1*l1/dot(q,q) - 1.0;
|
||||||
|
|
||||||
|
if( s<0.0 ) return vec2(-100.0);
|
||||||
|
|
||||||
|
return q + q.yx*vec2(-1.0,1.0)*side*sqrt( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a pyramid-like periodic signal.
|
||||||
|
float pyramid(float x)
|
||||||
|
{
|
||||||
|
x = fract(x);
|
||||||
|
return min(x * 2.0, (1.0 - x) * 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a semicircular periodic signal.
|
||||||
|
float circ(float x)
|
||||||
|
{
|
||||||
|
x = fract(x) * 2.0 - 1.0;
|
||||||
|
return sqrt(1.0 - x * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_IQ_SMIN
|
||||||
|
float smin(float a,float b,float k){ return -log(exp(-k*a)+exp(-k*b))/k;}//from iq
|
||||||
|
#else
|
||||||
|
// http://www.johndcook.com/blog/2010/01/20/how-to-compute-the-soft-maximum/
|
||||||
|
float smin(in float a, in float b, in float k) { return a - log(1.0+exp(k*(a-b))) / k; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float mp(float x)
|
||||||
|
{
|
||||||
|
float y=0.3;
|
||||||
|
return clamp((pyramid(x)-0.5)*2.0-0.4,-y,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float mosaic(vec3 p)
|
||||||
|
{
|
||||||
|
// Disabled because it causes a compilation failure due to time-out or size limit.
|
||||||
|
return 0.0;//max(mp(p.y*10.0),mp(p.z*10.0))*0.01;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
mat3 transpose(mat3 m)
|
||||||
|
{
|
||||||
|
return mat3(vec3(m[0].x,m[1].x,m[2].x),
|
||||||
|
vec3(m[0].y,m[1].y,m[2].y),
|
||||||
|
vec3(m[0].z,m[1].z,m[2].z));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
float capsuleDist(vec3 p,vec3 o,vec3 d,float h0,float h1,float r0,float r1)
|
||||||
|
{
|
||||||
|
vec3 u=cross(d,vec3(1.0,0.0,0.0));
|
||||||
|
vec3 v=cross(u,d);
|
||||||
|
u=cross(v,d);
|
||||||
|
mat3 m=transpose(mat3(normalize(u),normalize(v),normalize(d)));
|
||||||
|
d=normalize(d);
|
||||||
|
float t=clamp(dot(p-o,d),h0,h1);
|
||||||
|
vec3 np=o+t*d;
|
||||||
|
return distance(np,p)-mix(r0,r1,t)+mosaic(m*(p-o));
|
||||||
|
}
|
||||||
|
|
||||||
|
float boxDist(vec3 p,vec3 s,float r)
|
||||||
|
{
|
||||||
|
return length(max(vec3(0.0),abs(p)-s))-r+mosaic(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sphereDist(vec3 p,vec3 o,float r)
|
||||||
|
{
|
||||||
|
return distance(p,o)-r+mosaic(p-o);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sceneDist(vec3 p)
|
||||||
|
{
|
||||||
|
float d=1e3;
|
||||||
|
|
||||||
|
p+=vec3(0.0,0.07,0.0)*scene_scale;
|
||||||
|
p=rotateYMat(3.1415926*0.5)*p;
|
||||||
|
|
||||||
|
p.z+=cos(p.y*2.0+time)*0.1;
|
||||||
|
float tm=fract(time*wc_scale*2.0-0.1);
|
||||||
|
p.x-=(smoothstep(0.0,0.3,tm)-smoothstep(0.4,1.0,tm))*smoothstep(0.5,2.0,p.y)*0.2+scroll;
|
||||||
|
|
||||||
|
// Leg 0
|
||||||
|
{
|
||||||
|
float g=0.08;
|
||||||
|
vec3 o=vec3(0.0,0.0,0.2);
|
||||||
|
float d0=capsuleDist(p+o,vec3(leg0[0],0.0),vec3(leg0[1]-leg0[0],0.0),0.0,1.0-g,0.1,0.1);
|
||||||
|
float d1=capsuleDist(p+o,vec3(leg0[1],0.0),vec3(leg0[2]-leg0[1],0.0),g,1.0,0.1,0.2);
|
||||||
|
d=min(d,smin(d0,d1,15.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leg 1
|
||||||
|
{
|
||||||
|
float g=0.08;
|
||||||
|
vec3 o=vec3(0.0,0.0,-0.2);
|
||||||
|
float d0=capsuleDist(p+o,vec3(leg1[0],0.0),vec3(leg1[1]-leg1[0],0.0),0.0,1.0-g,0.1,0.1);
|
||||||
|
float d1=capsuleDist(p+o,vec3(leg1[1],0.0),vec3(leg1[2]-leg1[1],0.0),g,1.0,0.1,0.2);
|
||||||
|
d=min(d,smin(d0,d1,15.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
p.y-=bob;
|
||||||
|
|
||||||
|
// Arm 0
|
||||||
|
{
|
||||||
|
float g=0.08;
|
||||||
|
vec3 o=vec3(0.0,0.0,0.4);
|
||||||
|
mat3 m=rotateXMat(-0.3)*rotateYMat((cos((time*wc_scale+0.5)*3.1415926*2.0)-0.6)*0.5);
|
||||||
|
float d0=capsuleDist(p+o,vec3(arm0[0],0.0),m*vec3(arm0[1]-arm0[0],0.0),0.0,0.7-g,0.03,0.03);
|
||||||
|
float d1=capsuleDist(p+o,vec3(arm0[0],0.0)+m*vec3(arm0[1]-arm0[0],0.0),m*vec3(arm0[2]-arm0[1],0.0),g,0.7,0.03,0.06);
|
||||||
|
d=min(d,smin(d0,d1,15.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arm 1
|
||||||
|
{
|
||||||
|
float g=0.08;
|
||||||
|
vec3 o=vec3(0.0,0.0,-0.4);
|
||||||
|
mat3 m=rotateXMat(0.3)*rotateYMat(-(cos(time*wc_scale*3.1415926*2.0)-0.6)*0.5);
|
||||||
|
float d0=capsuleDist(p+o,vec3(arm1[0],0.0),m*vec3(arm1[1]-arm1[0],0.0),0.0,0.7-g,0.03,0.03);
|
||||||
|
float d1=capsuleDist(p+o,vec3(arm1[0],0.0)+m*vec3(arm1[1]-arm1[0],0.0),m*vec3(arm1[2]-arm1[1],0.0),g,0.7,0.03,0.06);
|
||||||
|
d=min(d,smin(d0,d1,15.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Torso
|
||||||
|
d=smin(d,boxDist(p+vec3(0.0,-0.7,0.0),vec3(0.05,0.7,0.15),0.1),15.0);
|
||||||
|
d=smin(d,boxDist(p+vec3(-0.1,-1.1,0.0),vec3(0.05,0.2,0.15)*0.1,0.1),5.0);
|
||||||
|
|
||||||
|
// Head
|
||||||
|
d=smin(d,sphereDist(p,vec3(0.0,1.825,0.0),0.2),15.0);
|
||||||
|
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sceneNorm(vec3 p)
|
||||||
|
{
|
||||||
|
p*=scene_scale;
|
||||||
|
float c=sceneDist(p);
|
||||||
|
float e=1e-3;
|
||||||
|
return normalize(vec3(sceneDist(p+vec3(e,0,0))-c,
|
||||||
|
sceneDist(p+vec3(0,e,0))-c,
|
||||||
|
sceneDist(p+vec3(0,0,e))-c));
|
||||||
|
}
|
||||||
|
|
||||||
|
float robot(vec3 ro,vec3 rd)
|
||||||
|
{
|
||||||
|
float t=0.0;
|
||||||
|
float tm;
|
||||||
|
|
||||||
|
tm=time*wc_scale;
|
||||||
|
|
||||||
|
leg0[0]=vec2(0.0,bob);
|
||||||
|
leg0[2]=vec2(pyramid(tm)-0.3,-1.8+0.3*circ(tm*2.0)*step(fract(tm),0.5));
|
||||||
|
leg0[1]=(leg0[0]+solve(leg0[2]-leg0[0],1.0,1.0,1.0));
|
||||||
|
|
||||||
|
arm1[0]=vec2(0.0,1.4);
|
||||||
|
arm1[2]=vec2(pyramid(tm)-0.3,0.1+pow(pyramid(tm),2.0)*0.7);
|
||||||
|
arm1[1]=(arm1[0]+solve(arm1[2]-arm1[0],0.7,0.7,-1.0));
|
||||||
|
|
||||||
|
tm+=0.5;
|
||||||
|
|
||||||
|
leg1[0]=vec2(0.0,bob);
|
||||||
|
leg1[2]=vec2(pyramid(tm)-0.3,-1.8+0.3*circ(tm*2.0)*step(fract(tm),0.5));
|
||||||
|
leg1[1]=(leg1[0]+solve(leg1[2]-leg1[0],1.0,1.0,1.0));
|
||||||
|
|
||||||
|
arm0[0]=vec2(0.0,1.4);
|
||||||
|
arm0[2]=vec2(pyramid(tm)-0.3,0.1+pow(pyramid(tm),2.0)*0.7);
|
||||||
|
arm0[1]=(arm0[0]+solve(arm0[2]-arm0[0],0.7,0.7,-1.0));
|
||||||
|
|
||||||
|
float rt=1e4;
|
||||||
|
|
||||||
|
ro*=scene_scale;
|
||||||
|
rd*=scene_scale;
|
||||||
|
|
||||||
|
for(int i=0;i<15;i+=1)
|
||||||
|
{
|
||||||
|
vec3 rp=ro+rd*t;
|
||||||
|
|
||||||
|
float d=sceneDist(rp);
|
||||||
|
|
||||||
|
if(d<1e-2)
|
||||||
|
{
|
||||||
|
rt=t;
|
||||||
|
}
|
||||||
|
|
||||||
|
t+=d/scene_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec2 unitSquareInterval(vec2 ro, vec2 rd)
|
||||||
|
{
|
||||||
|
vec2 slabs0 = (vec2(+1.0) - ro) / rd;
|
||||||
|
vec2 slabs1 = (vec2(-1.0) - ro) / rd;
|
||||||
|
|
||||||
|
vec2 mins = min(slabs0, slabs1);
|
||||||
|
vec2 maxs = max(slabs0, slabs1);
|
||||||
|
|
||||||
|
return vec2(max(mins.x, mins.y),
|
||||||
|
min(maxs.x, maxs.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 squaresColours(vec2 p)
|
||||||
|
{
|
||||||
|
p+=vec2(time*0.2);
|
||||||
|
|
||||||
|
vec3 orange=vec3(1.0,0.4,0.1)*2.0;
|
||||||
|
vec3 purple=vec3(1.0,0.2,0.5)*0.8;
|
||||||
|
|
||||||
|
float l=pow(0.5+0.5*cos(p.x*7.0+cos(p.y)*8.0)*sin(p.y*2.0),4.0)*2.0;
|
||||||
|
vec3 c=pow(l*(mix(orange,purple,0.5+0.5*cos(p.x*40.0+sin(p.y*10.0)*3.0))+
|
||||||
|
mix(orange,purple,0.5+0.5*cos(p.x*20.0+sin(p.y*3.0)*3.0))),vec3(1.2))*0.7;
|
||||||
|
|
||||||
|
c+=vec3(1.0,0.8,0.4)*pow(0.5+0.5*cos(p.x*20.0)*sin(p.y*12.0),20.0)*2.0;
|
||||||
|
|
||||||
|
c+=vec3(0.1,0.5+0.5*cos(p*20.0))*vec3(0.05,0.1,0.4).bgr*0.7;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 squaresTex(vec2 p,float border)
|
||||||
|
{
|
||||||
|
float sm=0.02;
|
||||||
|
vec2 res=vec2(8.0);
|
||||||
|
vec2 ip=floor(p*res)/res;
|
||||||
|
vec2 fp=fract(p*res);
|
||||||
|
float m=1.0-max(smoothstep(border-sm,border,abs(fp.x-0.5)),smoothstep(border-sm,border,abs(fp.y-0.5)));
|
||||||
|
m+=1.0-smoothstep(0.0,0.56,distance(fp,vec2(0.5)));
|
||||||
|
return m*squaresColours(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 room(vec3 ro,vec3 rd,out vec3 rp,out vec3 n)
|
||||||
|
{
|
||||||
|
vec2 box_size=vec2(1.0,5.0+3.0/8.0);
|
||||||
|
|
||||||
|
vec2 cp=vec2(0.0),ct=vec2(1e3);
|
||||||
|
|
||||||
|
for(int i=0;i<4;i+=1)
|
||||||
|
{
|
||||||
|
float cr=0.03;
|
||||||
|
vec2 tcp=vec2(2.5/8.0*float(-1),float(i)-2.0+0.5/8.0);
|
||||||
|
vec2 tct=intersectCircle((ro.xz-tcp)/cr,rd.xz/cr);
|
||||||
|
|
||||||
|
if(tct.y > 0.0 && tct.y<ct.y)
|
||||||
|
{
|
||||||
|
ct=tct;
|
||||||
|
cp=tcp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<4;i+=1)
|
||||||
|
{
|
||||||
|
float cr=0.03;
|
||||||
|
vec2 tcp=vec2(2.5/8.0*float(+1),float(i)-2.0+0.5/8.0);
|
||||||
|
vec2 tct=intersectCircle((ro.xz-tcp)/cr,rd.xz/cr);
|
||||||
|
|
||||||
|
if(tct.y > 0.0 && tct.y<ct.y)
|
||||||
|
{
|
||||||
|
ct=tct;
|
||||||
|
cp=tcp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ct.y=max(0.0,ct.y);
|
||||||
|
|
||||||
|
vec3 ci=ro+rd*ct.y;
|
||||||
|
vec2 cu=vec2(atan(ci.z-cp.y,ci.x-cp.x)/3.1415926*0.5,(ci.y+0.5/8.0)*4.0);
|
||||||
|
|
||||||
|
float wt=max(0.0,unitSquareInterval(ro.xy * box_size, rd.xy * box_size).y);
|
||||||
|
float t=min(ct.y,wt);
|
||||||
|
|
||||||
|
rp=ro+rd*(t-1e-4);
|
||||||
|
|
||||||
|
n.z=0.0;
|
||||||
|
if(abs(rp.x*box_size.x)>abs(rp.y*box_size.y))
|
||||||
|
n.xy=vec2(rp.x/abs(rp.x),0.0);
|
||||||
|
else
|
||||||
|
n.xy=vec2(0.0,rp.y/abs(rp.y));
|
||||||
|
|
||||||
|
if(ct.y<wt)
|
||||||
|
{
|
||||||
|
n.y=0.0;
|
||||||
|
n.xz=normalize(rp.xz-ci.xz);
|
||||||
|
}
|
||||||
|
|
||||||
|
float l=1.0-smoothstep(0.0,3.0,abs(rp.z-ro.z));
|
||||||
|
|
||||||
|
vec3 wc=mix(squaresTex(rp.zy+vec2(0.0,0.5/8.0),0.5),squaresTex(rp.xz,0.44),step(0.999/box_size.y,abs(rp.y)));
|
||||||
|
vec3 cc=squaresTex(cu,0.45)+0.8*vec3(smoothstep(0.83/5.0,0.86/5.0,abs(rp.y)));
|
||||||
|
|
||||||
|
return l*mix(cc,wc,step(wt,t));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 scene(vec2 p)
|
||||||
|
{
|
||||||
|
mat3 cam = rotateXMat(cos(time * 0.2) * 0.1) * rotateYMat(time * 0.5);
|
||||||
|
float lt=mod(time*wc_scale,wlen)/wlen;
|
||||||
|
|
||||||
|
vec3 ro = cam*vec3(0.0,-0.15+lt*0.15, 0.15+lt*0.2)+vec3(0.0,0.0,scroll/scene_scale);
|
||||||
|
vec3 rd = cam*vec3(p, -1.0);
|
||||||
|
|
||||||
|
rd=normalize(rd);
|
||||||
|
|
||||||
|
float robot_t=robot(ro,rd);
|
||||||
|
|
||||||
|
vec3 n,rp;
|
||||||
|
|
||||||
|
vec3 c;
|
||||||
|
vec3 c0=room(ro,rd,rp,n);
|
||||||
|
|
||||||
|
if(robot_t < distance(ro,rp))
|
||||||
|
{
|
||||||
|
rp=ro+rd*robot_t;
|
||||||
|
n=sceneNorm(rp);
|
||||||
|
vec3 r=reflect(rd,n);
|
||||||
|
c=vec3(0.5+0.5*n.y)*0.5*vec3(1.0,0.8,0.5);
|
||||||
|
vec3 c1=room(rp,r,rp,n);
|
||||||
|
c+=c1*0.5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec3 r=reflect(rd,n);
|
||||||
|
vec3 c1=room(rp,r,rp,n);
|
||||||
|
c=c0+c1*c0*0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ll=vec3(1.0-(smoothstep(0.0,0.07,lt)-smoothstep(0.93,1.0,lt)));
|
||||||
|
|
||||||
|
return ll+c+
|
||||||
|
0.6*((sin(p.y)*cos(p.x+time*2.0)*0.5+0.5)*
|
||||||
|
pow(mix(vec3(1.0,0.7,0.1),vec3(1.0,0.2,0.6),0.5+0.5*cos(p.x+sin(time*3.0+p.y*2.0))),vec3(2.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
time=iGlobalTime+1.0;
|
||||||
|
bob=cos(time*12.0)*0.05;
|
||||||
|
scroll=-15.0+mod(time*wc_scale,wlen)*2.0;
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
vec2 q=uv;
|
||||||
|
vec2 t=uv*2.0-vec2(1.0);
|
||||||
|
t.x*=iResolution.x/iResolution.y;
|
||||||
|
fragColor.a = 1.0f;
|
||||||
|
fragColor.rgb = scene(t.xy) * 1.3;
|
||||||
|
|
||||||
|
// vignet
|
||||||
|
fragColor.rgb *= 0.5 + 0.5*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
541
procedural/hlorenzi-super-mario-bros.slang
Normal file
541
procedural/hlorenzi-super-mario-bros.slang
Normal file
|
@ -0,0 +1,541 @@
|
||||||
|
#version 450
|
||||||
|
// Super Mario Bros. by HLorenzi
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Uncomment for totally random level!
|
||||||
|
// Just to show off Mario's dynamic movements :P
|
||||||
|
//#define TOTALLY_RANDOM_LEVEL 1
|
||||||
|
|
||||||
|
|
||||||
|
// Positions to start and end Mario simulation (relative to screen position)
|
||||||
|
// You can try changing these! (the difference between the two should be a multiple of 4)
|
||||||
|
// Put startX too close to endX, and Mario'll experience jittering!
|
||||||
|
#define startX 0.0
|
||||||
|
#define endX 80.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define RGB(r,g,b) vec4(float(r)/255.0,float(g)/255.0,float(b)/255.0,1.0)
|
||||||
|
|
||||||
|
#define SPRROW(x,a,b,c,d,e,f,g,h, i,j,k,l,m,n,o,p) (x <= 7 ? SPRROW_H(a,b,c,d,e,f,g,h) : SPRROW_H(i,j,k,l,m,n,o,p))
|
||||||
|
#define SPRROW_H(a,b,c,d,e,f,g,h) (a+4.0*(b+4.0*(c+4.0*(d+4.0*(e+4.0*(f+4.0*(g+4.0*(h))))))))
|
||||||
|
#define SECROW(x,a,b,c,d,e,f,g,h) (x <= 3 ? SECROW_H(a,b,c,d) : SECROW_H(e,f,g,h))
|
||||||
|
#define SECROW_H(a,b,c,d) (a+8.0*(b+8.0*(c+8.0*(d))))
|
||||||
|
#define SELECT(x,i) mod(floor(i/pow(4.0,float(x))),4.0)
|
||||||
|
#define SELECTSEC(x,i) mod(floor(i/pow(8.0,float(x))),8.0)
|
||||||
|
|
||||||
|
float rand(vec2 co)
|
||||||
|
{
|
||||||
|
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sprGround(int x, int y)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
if (y == 15) col = SPRROW(x,1.,0.,0.,0.,0.,0.,0.,0., 0.,2.,1.,0.,0.,0.,0.,1.);
|
||||||
|
if (y == 14) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,0.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 13) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,0.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 12) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,0.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 11) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,0.,2.,1.,1.,1.,2.);
|
||||||
|
if (y == 10) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,1.,2.,2.,2.,2.,1.);
|
||||||
|
if (y == 9) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,0.,0.,0.,0.,0.,2.);
|
||||||
|
if (y == 8) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,0.,1.,1.,1.,1.,2.);
|
||||||
|
|
||||||
|
if (y == 7) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,0.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 6) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,2.,0.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 5) col = SPRROW(x,2.,2.,1.,1.,1.,1.,1.,1., 2.,0.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 4) col = SPRROW(x,0.,0.,2.,2.,1.,1.,1.,1., 2.,0.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 3) col = SPRROW(x,0.,1.,0.,0.,2.,2.,2.,2., 0.,1.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 2) col = SPRROW(x,0.,1.,1.,1.,0.,0.,0.,2., 0.,1.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 1) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,2., 0.,1.,1.,1.,1.,1.,2.,2.);
|
||||||
|
if (y == 0) col = SPRROW(x,1.,2.,2.,2.,2.,2.,2.,1., 0.,2.,2.,2.,2.,2.,2.,1.);
|
||||||
|
|
||||||
|
col = SELECT(mod(float(x),8.0),col);
|
||||||
|
if (col == 0.0) return RGB(247,214,181);
|
||||||
|
if (col == 1.0) return RGB(231,90,16);
|
||||||
|
return RGB(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sprQuestionBlock(int x, int y)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
if (y == 15) col = SPRROW(x,3.,0.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,3.);
|
||||||
|
if (y == 14) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 13) col = SPRROW(x,0.,1.,2.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,2.,1.,2.);
|
||||||
|
if (y == 12) col = SPRROW(x,0.,1.,1.,1.,1.,0.,0.,0., 0.,0.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 11) col = SPRROW(x,0.,1.,1.,1.,0.,0.,2.,2., 2.,0.,0.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 10) col = SPRROW(x,0.,1.,1.,1.,0.,0.,2.,1., 1.,0.,0.,2.,1.,1.,1.,2.);
|
||||||
|
if (y == 9) col = SPRROW(x,0.,1.,1.,1.,0.,0.,2.,1., 1.,0.,0.,2.,1.,1.,1.,2.);
|
||||||
|
if (y == 8) col = SPRROW(x,0.,1.,1.,1.,1.,2.,2.,1., 0.,0.,0.,2.,1.,1.,1.,2.);
|
||||||
|
|
||||||
|
if (y == 7) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,0., 0.,2.,2.,2.,1.,1.,1.,2.);
|
||||||
|
if (y == 6) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,0., 0.,2.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 5) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 2.,2.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 4) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,0., 0.,0.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 3) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,0., 0.,2.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 2) col = SPRROW(x,0.,1.,2.,1.,1.,1.,1.,1., 2.,2.,1.,1.,1.,2.,1.,2.);
|
||||||
|
if (y == 1) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,2.);
|
||||||
|
if (y == 0) col = SPRROW(x,2.,2.,2.,2.,2.,2.,2.,2., 2.,2.,2.,2.,2.,2.,2.,2.);
|
||||||
|
|
||||||
|
if (y < 0 || y > 15) return RGB(107,140,255);
|
||||||
|
|
||||||
|
col = SELECT(mod(float(x),8.0),col);
|
||||||
|
if (col == 0.0) return RGB(231,90,16);
|
||||||
|
if (col == 1.0) return RGB(255,165,66);
|
||||||
|
if (col == 2.0) return RGB(0,0,0);
|
||||||
|
return RGB(107,140,255);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sprUsedBlock(int x, int y)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
if (y == 15) col = SPRROW(x,3.,0.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,3.);
|
||||||
|
if (y == 14) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 13) col = SPRROW(x,0.,1.,0.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,0.,1.,0.);
|
||||||
|
if (y == 12) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 11) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 10) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 9) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 8) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
|
||||||
|
if (y == 7) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 6) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 5) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 4) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 3) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 2) col = SPRROW(x,0.,1.,0.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,0.,1.,0.);
|
||||||
|
if (y == 1) col = SPRROW(x,0.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,0.);
|
||||||
|
if (y == 0) col = SPRROW(x,3.,0.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,3.);
|
||||||
|
|
||||||
|
if (y < 0 || y > 15) return RGB(107,140,255);
|
||||||
|
|
||||||
|
col = SELECT(mod(float(x),8.0),col);
|
||||||
|
if (col == 0.0) return RGB(0,0,0);
|
||||||
|
if (col == 1.0) return RGB(231,90,16);
|
||||||
|
return RGB(107,140,255);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sprMarioJump(int x, int y)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
if (y == 15) col = SPRROW(x,0.,0.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,2.,2.,2.);
|
||||||
|
if (y == 14) col = SPRROW(x,0.,0.,0.,0.,0.,0.,1.,1., 1.,1.,1.,0.,0.,2.,2.,2.);
|
||||||
|
if (y == 13) col = SPRROW(x,0.,0.,0.,0.,0.,1.,1.,1., 1.,1.,1.,1.,1.,1.,2.,2.);
|
||||||
|
if (y == 12) col = SPRROW(x,0.,0.,0.,0.,0.,3.,3.,3., 2.,2.,3.,2.,0.,3.,3.,3.);
|
||||||
|
if (y == 11) col = SPRROW(x,0.,0.,0.,0.,3.,2.,3.,2., 2.,2.,3.,2.,2.,3.,3.,3.);
|
||||||
|
if (y == 10) col = SPRROW(x,0.,0.,0.,0.,3.,2.,3.,3., 2.,2.,2.,3.,2.,2.,2.,3.);
|
||||||
|
if (y == 9) col = SPRROW(x,0.,0.,0.,0.,3.,3.,2.,2., 2.,2.,3.,3.,3.,3.,3.,0.);
|
||||||
|
if (y == 8) col = SPRROW(x,0.,0.,0.,0.,0.,0.,2.,2., 2.,2.,2.,2.,2.,3.,0.,0.);
|
||||||
|
|
||||||
|
if (y == 7) col = SPRROW(x,0.,0.,3.,3.,3.,3.,3.,1., 3.,3.,3.,1.,3.,0.,0.,0.);
|
||||||
|
if (y == 6) col = SPRROW(x,0.,3.,3.,3.,3.,3.,3.,3., 1.,3.,3.,3.,1.,0.,0.,3.);
|
||||||
|
if (y == 5) col = SPRROW(x,2.,2.,3.,3.,3.,3.,3.,3., 1.,1.,1.,1.,1.,0.,0.,3.);
|
||||||
|
if (y == 4) col = SPRROW(x,2.,2.,2.,0.,1.,1.,3.,1., 1.,2.,1.,1.,2.,1.,3.,3.);
|
||||||
|
if (y == 3) col = SPRROW(x,0.,2.,0.,3.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,3.,3.);
|
||||||
|
if (y == 2) col = SPRROW(x,0.,0.,3.,3.,3.,1.,1.,1., 1.,1.,1.,1.,1.,1.,3.,3.);
|
||||||
|
if (y == 1) col = SPRROW(x,0.,3.,3.,3.,1.,1.,1.,1., 1.,1.,1.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 0) col = SPRROW(x,0.,3.,0.,0.,1.,1.,1.,1., 0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
|
||||||
|
col = SELECT(mod(float(x),8.0),col);
|
||||||
|
if (col == 0.0) return RGB(0,0,0);
|
||||||
|
if (col == 1.0) return RGB(177,52,37);
|
||||||
|
if (col == 2.0) return RGB(227,157,37);
|
||||||
|
if (col == 3.0) return RGB(106,107,4);
|
||||||
|
return RGB(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sprMarioWalk3(int x, int y)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
if (y == 15) col = SPRROW(x,0.,0.,0.,0.,0.,1.,1.,1., 1.,1.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 14) col = SPRROW(x,0.,0.,0.,0.,1.,1.,1.,1., 1.,1.,1.,1.,1.,0.,0.,0.);
|
||||||
|
if (y == 13) col = SPRROW(x,0.,0.,0.,0.,3.,3.,3.,2., 2.,3.,2.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 12) col = SPRROW(x,0.,0.,0.,3.,2.,3.,2.,2., 2.,3.,2.,2.,2.,0.,0.,0.);
|
||||||
|
if (y == 11) col = SPRROW(x,0.,0.,0.,3.,2.,3.,3.,2., 2.,2.,3.,2.,2.,2.,0.,0.);
|
||||||
|
if (y == 10) col = SPRROW(x,0.,0.,0.,3.,3.,2.,2.,2., 2.,3.,3.,3.,3.,0.,0.,0.);
|
||||||
|
if (y == 9) col = SPRROW(x,0.,0.,0.,0.,0.,2.,2.,2., 2.,2.,2.,2.,0.,0.,0.,0.);
|
||||||
|
if (y == 8) col = SPRROW(x,0.,0.,3.,3.,3.,3.,1.,1., 3.,3.,0.,0.,0.,0.,0.,0.);
|
||||||
|
|
||||||
|
if (y == 7) col = SPRROW(x,2.,2.,3.,3.,3.,3.,1.,1., 1.,3.,3.,3.,2.,2.,2.,0.);
|
||||||
|
if (y == 6) col = SPRROW(x,2.,2.,2.,0.,3.,3.,1.,2., 1.,1.,1.,3.,3.,2.,2.,0.);
|
||||||
|
if (y == 5) col = SPRROW(x,2.,2.,0.,0.,1.,1.,1.,1., 1.,1.,1.,0.,0.,3.,0.,0.);
|
||||||
|
if (y == 4) col = SPRROW(x,0.,0.,0.,1.,1.,1.,1.,1., 1.,1.,1.,1.,3.,3.,0.,0.);
|
||||||
|
if (y == 3) col = SPRROW(x,0.,0.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,3.,3.,0.,0.);
|
||||||
|
if (y == 2) col = SPRROW(x,0.,3.,3.,1.,1.,1.,0.,0., 0.,1.,1.,1.,3.,3.,0.,0.);
|
||||||
|
if (y == 1) col = SPRROW(x,0.,3.,3.,3.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 0) col = SPRROW(x,0.,0.,3.,3.,3.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
|
||||||
|
col = SELECT(mod(float(x),8.0),col);
|
||||||
|
if (col == 0.0) return RGB(0,0,0);
|
||||||
|
if (col == 1.0) return RGB(177,52,37);
|
||||||
|
if (col == 2.0) return RGB(227,157,37);
|
||||||
|
if (col == 3.0) return RGB(106,107,4);
|
||||||
|
return RGB(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec4 sprMarioWalk2(int x, int y)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
if (y == 15) col = SPRROW(x,0.,0.,0.,0.,0.,1.,1.,1., 1.,1.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 14) col = SPRROW(x,0.,0.,0.,0.,1.,1.,1.,1., 1.,1.,1.,1.,1.,0.,0.,0.);
|
||||||
|
if (y == 13) col = SPRROW(x,0.,0.,0.,0.,3.,3.,3.,2., 2.,3.,2.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 12) col = SPRROW(x,0.,0.,0.,3.,2.,3.,2.,2., 2.,3.,2.,2.,2.,0.,0.,0.);
|
||||||
|
if (y == 11) col = SPRROW(x,0.,0.,0.,3.,2.,3.,3.,2., 2.,2.,3.,2.,2.,2.,0.,0.);
|
||||||
|
if (y == 10) col = SPRROW(x,0.,0.,0.,3.,3.,2.,2.,2., 2.,3.,3.,3.,3.,0.,0.,0.);
|
||||||
|
if (y == 9) col = SPRROW(x,0.,0.,0.,0.,0.,2.,2.,2., 2.,2.,2.,2.,0.,0.,0.,0.);
|
||||||
|
if (y == 8) col = SPRROW(x,0.,0.,0.,0.,3.,3.,1.,3., 3.,3.,0.,0.,0.,0.,0.,0.);
|
||||||
|
|
||||||
|
if (y == 7) col = SPRROW(x,0.,0.,0.,3.,3.,3.,3.,1., 1.,3.,3.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 6) col = SPRROW(x,0.,0.,0.,3.,3.,3.,1.,1., 2.,1.,1.,2.,0.,0.,0.,0.);
|
||||||
|
if (y == 5) col = SPRROW(x,0.,0.,0.,3.,3.,3.,3.,1., 1.,1.,1.,1.,0.,0.,0.,0.);
|
||||||
|
if (y == 4) col = SPRROW(x,0.,0.,0.,1.,3.,3.,2.,2., 2.,1.,1.,1.,0.,0.,0.,0.);
|
||||||
|
if (y == 3) col = SPRROW(x,0.,0.,0.,0.,1.,3.,2.,2., 1.,1.,1.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 2) col = SPRROW(x,0.,0.,0.,0.,0.,1.,1.,1., 3.,3.,3.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 1) col = SPRROW(x,0.,0.,0.,0.,0.,3.,3.,3., 3.,3.,3.,3.,0.,0.,0.,0.);
|
||||||
|
if (y == 0) col = SPRROW(x,0.,0.,0.,0.,0.,3.,3.,3., 3.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
|
||||||
|
col = SELECT(mod(float(x),8.0),col);
|
||||||
|
if (col == 0.0) return RGB(0,0,0);
|
||||||
|
if (col == 1.0) return RGB(177,52,37);
|
||||||
|
if (col == 2.0) return RGB(227,157,37);
|
||||||
|
if (col == 3.0) return RGB(106,107,4);
|
||||||
|
return RGB(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec4 sprMarioWalk1(int x, int y)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
if (y == 15) col = SPRROW(x,0.,0.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 14) col = SPRROW(x,0.,0.,0.,0.,0.,0.,1.,1., 1.,1.,1.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 13) col = SPRROW(x,0.,0.,0.,0.,0.,1.,1.,1., 1.,1.,1.,1.,1.,1.,0.,0.);
|
||||||
|
if (y == 12) col = SPRROW(x,0.,0.,0.,0.,0.,3.,3.,3., 2.,2.,3.,2.,0.,0.,0.,0.);
|
||||||
|
if (y == 11) col = SPRROW(x,0.,0.,0.,0.,3.,2.,3.,2., 2.,2.,3.,2.,2.,2.,0.,0.);
|
||||||
|
if (y == 10) col = SPRROW(x,0.,0.,0.,0.,3.,2.,3.,3., 2.,2.,2.,3.,2.,2.,2.,0.);
|
||||||
|
if (y == 9) col = SPRROW(x,0.,0.,0.,0.,3.,3.,2.,2., 2.,2.,3.,3.,3.,3.,0.,0.);
|
||||||
|
if (y == 8) col = SPRROW(x,0.,0.,0.,0.,0.,0.,2.,2., 2.,2.,2.,2.,2.,0.,0.,0.);
|
||||||
|
|
||||||
|
if (y == 7) col = SPRROW(x,0.,0.,0.,0.,0.,3.,3.,3., 3.,1.,3.,0.,2.,0.,0.,0.);
|
||||||
|
if (y == 6) col = SPRROW(x,0.,0.,0.,0.,2.,3.,3.,3., 3.,3.,3.,2.,2.,2.,0.,0.);
|
||||||
|
if (y == 5) col = SPRROW(x,0.,0.,0.,2.,2.,1.,3.,3., 3.,3.,3.,2.,2.,0.,0.,0.);
|
||||||
|
if (y == 4) col = SPRROW(x,0.,0.,0.,3.,3.,1.,1.,1., 1.,1.,1.,1.,0.,0.,0.,0.);
|
||||||
|
if (y == 3) col = SPRROW(x,0.,0.,0.,3.,1.,1.,1.,1., 1.,1.,1.,1.,0.,0.,0.,0.);
|
||||||
|
if (y == 2) col = SPRROW(x,0.,0.,3.,3.,1.,1.,1.,0., 1.,1.,1.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 1) col = SPRROW(x,0.,0.,3.,0.,0.,0.,0.,3., 3.,3.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 0) col = SPRROW(x,0.,0.,0.,0.,0.,0.,0.,3., 3.,3.,3.,0.,0.,0.,0.,0.);
|
||||||
|
|
||||||
|
col = SELECT(mod(float(x),8.0),col);
|
||||||
|
if (col == 0.0) return RGB(0,0,0);
|
||||||
|
if (col == 1.0) return RGB(177,52,37);
|
||||||
|
if (col == 2.0) return RGB(227,157,37);
|
||||||
|
if (col == 3.0) return RGB(106,107,4);
|
||||||
|
return RGB(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 getTile(int t, int x, int y)
|
||||||
|
{
|
||||||
|
if (t == 0) return RGB(107,140,255);
|
||||||
|
if (t == 1) return sprGround(x,y);
|
||||||
|
if (t == 2) return sprQuestionBlock(x,y);
|
||||||
|
if (t == 3) return sprUsedBlock(x,y);
|
||||||
|
|
||||||
|
return RGB(107,140,255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getSection(int s, int x, int y)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
if (s == 0) {
|
||||||
|
if (y == 6) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 5) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 4) col = SECROW(x,0.,0.,3.,3.,3.,0.,0.,0.);
|
||||||
|
if (y == 3) col = SECROW(x,0.,0.,2.,2.,2.,0.,0.,0.);
|
||||||
|
if (y == 2) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 1) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y <= 0) col = SECROW(x,1.,1.,1.,1.,1.,1.,1.,1.);
|
||||||
|
}
|
||||||
|
if (s == 1) {
|
||||||
|
if (y == 6) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 5) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 4) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 3) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 2) col = SECROW(x,0.,0.,0.,0.,0.,1.,0.,0.);
|
||||||
|
if (y == 1) col = SECROW(x,0.,0.,0.,1.,1.,1.,0.,0.);
|
||||||
|
if (y <= 0) col = SECROW(x,1.,1.,1.,1.,1.,1.,1.,1.);
|
||||||
|
}
|
||||||
|
if (s == 2) {
|
||||||
|
if (y == 6) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 5) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 4) col = SECROW(x,0.,0.,3.,0.,0.,3.,0.,0.);
|
||||||
|
if (y == 3) col = SECROW(x,0.,0.,2.,0.,0.,2.,0.,0.);
|
||||||
|
if (y == 2) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 1) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y <= 0) col = SECROW(x,1.,1.,1.,1.,1.,1.,1.,1.);
|
||||||
|
}
|
||||||
|
if (s == 3) {
|
||||||
|
if (y == 6) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 5) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 4) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 3) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 2) col = SECROW(x,0.,0.,0.,1.,1.,0.,0.,0.);
|
||||||
|
if (y == 1) col = SECROW(x,0.,0.,0.,1.,1.,1.,0.,0.);
|
||||||
|
if (y <= 0) col = SECROW(x,1.,1.,1.,1.,1.,1.,1.,1.);
|
||||||
|
}
|
||||||
|
if (s == 4) {
|
||||||
|
if (y == 6) col = SECROW(x,0.,0.,0.,0.,3.,0.,0.,0.);
|
||||||
|
if (y == 5) col = SECROW(x,0.,0.,0.,0.,2.,0.,0.,0.);
|
||||||
|
if (y == 4) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 3) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 2) col = SECROW(x,0.,0.,0.,1.,1.,1.,0.,0.);
|
||||||
|
if (y == 1) col = SECROW(x,0.,0.,0.,1.,1.,1.,0.,0.);
|
||||||
|
if (y <= 0) col = SECROW(x,1.,1.,1.,1.,1.,1.,1.,1.);
|
||||||
|
}
|
||||||
|
if (s == 5) {
|
||||||
|
if (y == 6) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 5) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 4) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 3) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 2) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y == 1) col = SECROW(x,0.,0.,0.,0.,0.,0.,0.,0.);
|
||||||
|
if (y <= 0) col = SECROW(x,1.,1.,1.,0.,0.,1.,1.,1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return int(SELECTSEC(mod(float(x),4.0),col));
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBlock(int x, int y)
|
||||||
|
{
|
||||||
|
#ifdef TOTALLY_RANDOM_LEVEL
|
||||||
|
int height = 1 + int(rand(vec2(int(float(x) / 3.0),2.3)) * 3.0);
|
||||||
|
return (y < height ? 1 : 0);
|
||||||
|
#else
|
||||||
|
if (y > 6) return 0;
|
||||||
|
|
||||||
|
int section = int(rand(vec2(int(float(x) / 8.0),3.0)) * 6.0);
|
||||||
|
int sectionX = int(mod(float(x), 8.0));
|
||||||
|
|
||||||
|
return getSection(section,sectionX,y - int(rand(vec2(section,2.0)) * 0.0));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSolid(int b)
|
||||||
|
{
|
||||||
|
return (b != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
const float gameSpeed = 60.0;
|
||||||
|
|
||||||
|
// Get the current game pixel
|
||||||
|
// (Each game pixel is two screen pixels)
|
||||||
|
// (or four, if the screen is larger)
|
||||||
|
float x = fragCoord.x / 2.0;
|
||||||
|
float y = fragCoord.y / 2.0;
|
||||||
|
if (iResolution.y >= 640.0) {
|
||||||
|
x /= 2.0;
|
||||||
|
y /= 2.0;
|
||||||
|
}
|
||||||
|
if (iResolution.y < 200.0) {
|
||||||
|
x *= 2.0;
|
||||||
|
y *= 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just move the screen up for half a block's size
|
||||||
|
y -= 8.0;
|
||||||
|
|
||||||
|
// Get the grid index of the block at this pixel,
|
||||||
|
// and of the block at the screen's leftmost position
|
||||||
|
int firstBlockX = int((iGlobalTime * gameSpeed) / 16.0);
|
||||||
|
int blockX = int((x + iGlobalTime * gameSpeed) / 16.0);
|
||||||
|
int blockY = int(y / 16.0);
|
||||||
|
|
||||||
|
// Ask for the block ID that exists in the current position
|
||||||
|
int block = getBlock(blockX,blockY);
|
||||||
|
|
||||||
|
// Get the fractional position inside current block
|
||||||
|
int subx = int(mod((x + iGlobalTime * gameSpeed),16.0));
|
||||||
|
int suby = int(mod(y,16.0));
|
||||||
|
|
||||||
|
// Animate block if it's a Question Block
|
||||||
|
if (block == 2) {
|
||||||
|
if (blockX - firstBlockX == 5) {
|
||||||
|
suby -= int(max(0.0,(sin(mod((iGlobalTime * gameSpeed / 16.0),1.0) * 3.141592 * 1.5) * 8.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((floor((x + iGlobalTime * gameSpeed) / 16.0) - (iGlobalTime * gameSpeed) / 16.0) < 4.25) block = 3;
|
||||||
|
// Animate block if it's on top of a Question Block
|
||||||
|
} else if (block == 3) {
|
||||||
|
block = 2;
|
||||||
|
suby += 16;
|
||||||
|
if (blockX - firstBlockX == 5) {
|
||||||
|
suby -= int(max(0.0,(sin(mod((iGlobalTime * gameSpeed / 16.0),1.0) * 3.141592 * 1.5) * 8.0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get the final color for this pixel
|
||||||
|
// (Mario can override this later on)
|
||||||
|
fragColor = getTile(block,subx,suby);
|
||||||
|
|
||||||
|
|
||||||
|
// If this is the column where Mario stops simulating...
|
||||||
|
// (it's the only column he can appear in)
|
||||||
|
if (x >= endX && x < endX + 16.0) {
|
||||||
|
|
||||||
|
// Screen position in pixels:
|
||||||
|
// Every block is 16 pixels wide
|
||||||
|
float screenX = iGlobalTime * gameSpeed;
|
||||||
|
|
||||||
|
// Mario's starting position and speed
|
||||||
|
float marioX = screenX + startX;
|
||||||
|
float marioY = 16.0;
|
||||||
|
float marioXSpd = 4.0;
|
||||||
|
float marioYSpd = 0.0;
|
||||||
|
|
||||||
|
// Find out the first empty block in this column,
|
||||||
|
// starting from the bottom, as to put Mario on top of it
|
||||||
|
for(int i = 1; i < 4; i++) {
|
||||||
|
if (!isSolid(getBlock(int(marioX / 16.0), i))) {
|
||||||
|
marioY = float(i) * 16.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of steps to simulate;
|
||||||
|
// We'll simulate at 15 FPS and interpolate later,
|
||||||
|
// hence the division by 4.0
|
||||||
|
// (Mario should actually be walking 1 pixel every 1/60th of a second,
|
||||||
|
// but he'll be walking 4 pixels every 1/15th)
|
||||||
|
const int simSteps = int((endX - startX) / 4.0);
|
||||||
|
|
||||||
|
// Previous position, as to interpolate later, for high frame rates
|
||||||
|
float lastX = 0.0;
|
||||||
|
float lastY = 0.0;
|
||||||
|
|
||||||
|
// Start simulating
|
||||||
|
bool onGround = false;
|
||||||
|
for(int sim = 0; sim < simSteps; sim++) {
|
||||||
|
// Store the previous position
|
||||||
|
lastX = marioX;
|
||||||
|
lastY = marioY;
|
||||||
|
|
||||||
|
// If Mario is inside a block, move him up
|
||||||
|
// (This happens only at the start of the simulation,
|
||||||
|
// sometimes because he is heads-up with a wall and
|
||||||
|
// cannot make a jump properly)
|
||||||
|
onGround = false;
|
||||||
|
if (isSolid(getBlock(int(marioX / 16.0) + 1, int(marioY / 16.0)))) {
|
||||||
|
marioY = (floor(marioY / 16.0) * 16.0) + 16.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, pretty standard platforming code
|
||||||
|
|
||||||
|
// Apply gravity and move in the Y-axis
|
||||||
|
marioYSpd -= 2.5;
|
||||||
|
marioY += marioYSpd;
|
||||||
|
|
||||||
|
// If he is going up,
|
||||||
|
// and if there is a block above him,
|
||||||
|
// align him with the grid (as to avoid getting inside the block),
|
||||||
|
// and invert his YSpeed, as to fall quickly (because he bounced his head)
|
||||||
|
if (marioYSpd > 0.0) {
|
||||||
|
if (isSolid(getBlock(int(floor((marioX + 12.0) / 16.0)), int(floor((marioY + 15.9) / 16.0))))) {
|
||||||
|
marioYSpd *= -0.5;
|
||||||
|
marioY = (floor(marioY / 16.0) * 16.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If he is going down,
|
||||||
|
// and if there is a block beneath him,
|
||||||
|
// align him with the grid (as to land properly on top of the block),
|
||||||
|
// and mark him as onGround (to be able to perform a jump)
|
||||||
|
if (marioYSpd < 0.0) {
|
||||||
|
if (isSolid(getBlock(int(floor((marioX) / 16.0)), int(floor(marioY / 16.0)))) ||
|
||||||
|
isSolid(getBlock(int(floor((marioX + 15.9) / 16.0)), int(floor(marioY / 16.0))))) {
|
||||||
|
marioYSpd = 0.0;
|
||||||
|
marioY = (floor(marioY / 16.0) * 16.0) + 16.0;
|
||||||
|
onGround = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, move him in the X-axis
|
||||||
|
// I assume here he'll never hit a block horizontally
|
||||||
|
marioX += marioXSpd;
|
||||||
|
|
||||||
|
// Now, if he's onGround,
|
||||||
|
// and if there are blocks in front of him,
|
||||||
|
// or if there is a pit right next to him,
|
||||||
|
// set his YSpeed to jump
|
||||||
|
if (onGround) {
|
||||||
|
if (!isSolid(getBlock(int((marioX) / 16.0) + 1,0))) {
|
||||||
|
marioYSpd = 15.5;
|
||||||
|
} else if (isSolid(getBlock(int((marioX + 36.0) / 16.0), int((marioY + 24.0) / 16.0)))) {
|
||||||
|
marioYSpd = 15.5;
|
||||||
|
} else if (isSolid(getBlock(int((marioX) / 16.0) + 2, int((marioY + 8.0) / 16.0)))) {
|
||||||
|
marioYSpd = 12.5;
|
||||||
|
} else if (getBlock(int((marioX) / 16.0) + 1, int((marioY + 8.0) / 16.0) + 2) == 2) {
|
||||||
|
marioYSpd = 15.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolate Y-pos for smooth high-frame-rate movement
|
||||||
|
marioY = mix(lastY,marioY,mod(iGlobalTime * 15.0,1.0)) - 1.0;
|
||||||
|
|
||||||
|
// Finally, if he appears at this row, fetch a pixel from his sprites
|
||||||
|
if (y >= marioY && y < marioY + 16.0) {
|
||||||
|
vec4 spr = vec4(0,0,0,0);
|
||||||
|
if (onGround) {
|
||||||
|
// Which frame?
|
||||||
|
int f = int(mod(iGlobalTime * 10.0, 3.0));
|
||||||
|
if (f == 0) spr = sprMarioWalk1(int(x - (marioX - screenX)),int(y - marioY));
|
||||||
|
if (f == 1) spr = sprMarioWalk2(int(x - (marioX - screenX)),int(y - marioY));
|
||||||
|
if (f == 2) spr = sprMarioWalk3(int(x - (marioX - screenX)),int(y - marioY));
|
||||||
|
} else {
|
||||||
|
spr = sprMarioJump(int(x - (marioX - screenX)),int(y - marioY));
|
||||||
|
}
|
||||||
|
// Transparency check
|
||||||
|
if (spr.x != 0.0) fragColor = spr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
213
procedural/iq-julia-quaternion.slang
Normal file
213
procedural/iq-julia-quaternion.slang
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
#version 450
|
||||||
|
// Created by inigo quilez - iq/2013
|
||||||
|
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
|
||||||
|
// A port of my 2007 demo Kindernoiser: https://www.youtube.com/watch?v=9AX8gNyrSWc (http://www.pouet.net/prod.php?which=32549)
|
||||||
|
//
|
||||||
|
// More info here: http://iquilezles.org/www/articles/juliasets3d/juliasets3d.htm
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// antialias level (1, 2, 3...)
|
||||||
|
#define AA 1
|
||||||
|
|
||||||
|
float map( in vec3 p, out vec4 oTrap, in vec4 c )
|
||||||
|
{
|
||||||
|
vec4 z = vec4(p,0.0);
|
||||||
|
float md2 = 1.0;
|
||||||
|
float mz2 = dot(z,z);
|
||||||
|
|
||||||
|
vec4 trap = vec4(abs(z.xyz),dot(z,z));
|
||||||
|
|
||||||
|
for( int i=0; i<11; i++ )
|
||||||
|
{
|
||||||
|
// |dz|^2 -> 4*|dz|^2
|
||||||
|
md2 *= 4.0*mz2;
|
||||||
|
|
||||||
|
// z -> z2 + c
|
||||||
|
z = vec4( z.x*z.x-dot(z.yzw,z.yzw),
|
||||||
|
2.0*z.x*z.yzw ) + c;
|
||||||
|
|
||||||
|
trap = min( trap, vec4(abs(z.xyz),dot(z,z)) );
|
||||||
|
|
||||||
|
mz2 = dot(z,z);
|
||||||
|
if(mz2>4.0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
oTrap = trap;
|
||||||
|
|
||||||
|
return 0.25*sqrt(mz2/md2)*log(mz2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// analytic normal for quadratic formula
|
||||||
|
vec3 calcNormal( in vec3 p, in vec4 c )
|
||||||
|
{
|
||||||
|
vec4 z = vec4(p,0.0);
|
||||||
|
|
||||||
|
vec4 dz0 = vec4(1.0,0.0,0.0,0.0);
|
||||||
|
vec4 dz1 = vec4(0.0,1.0,0.0,0.0);
|
||||||
|
vec4 dz2 = vec4(0.0,0.0,1.0,0.0);
|
||||||
|
vec4 dz3 = vec4(0.0,0.0,0.0,1.0);
|
||||||
|
|
||||||
|
for(int i=0;i<11;i++)
|
||||||
|
{
|
||||||
|
vec4 mz = vec4(z.x,-z.y,-z.z,-z.w);
|
||||||
|
|
||||||
|
// derivative
|
||||||
|
dz0 = vec4(dot(mz,dz0),z.x*dz0.yzw+dz0.x*z.yzw);
|
||||||
|
dz1 = vec4(dot(mz,dz1),z.x*dz1.yzw+dz1.x*z.yzw);
|
||||||
|
dz2 = vec4(dot(mz,dz2),z.x*dz2.yzw+dz2.x*z.yzw);
|
||||||
|
dz3 = vec4(dot(mz,dz3),z.x*dz3.yzw+dz3.x*z.yzw);
|
||||||
|
|
||||||
|
z = vec4( dot(z, mz), 2.0*z.x*z.yzw ) + c;
|
||||||
|
|
||||||
|
if( dot(z,z)>4.0 ) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalize(vec3(dot(z,dz0),
|
||||||
|
dot(z,dz1),
|
||||||
|
dot(z,dz2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float intersect( in vec3 ro, in vec3 rd, out vec4 res, in vec4 c )
|
||||||
|
{
|
||||||
|
vec4 tmp;
|
||||||
|
float resT = -1.0;
|
||||||
|
float maxd = 10.0;
|
||||||
|
float h = 1.0;
|
||||||
|
float t = 0.0;
|
||||||
|
for( int i=0; i<150; i++ )
|
||||||
|
{
|
||||||
|
if( h<0.002||t>maxd ) break;
|
||||||
|
h = map( ro+rd*t, tmp, c );
|
||||||
|
t += h;
|
||||||
|
}
|
||||||
|
if( t<maxd ) { resT=t; res = tmp; }
|
||||||
|
|
||||||
|
return resT;
|
||||||
|
}
|
||||||
|
|
||||||
|
float softshadow( in vec3 ro, in vec3 rd, float mint, float k, in vec4 c )
|
||||||
|
{
|
||||||
|
float res = 1.0;
|
||||||
|
float t = mint;
|
||||||
|
for( int i=0; i<64; i++ )
|
||||||
|
{
|
||||||
|
vec4 kk;
|
||||||
|
float h = map(ro + rd*t, kk, c);
|
||||||
|
res = min( res, k*h/t );
|
||||||
|
if( res<0.001 ) break;
|
||||||
|
t += clamp( h, 0.01, 0.5 );
|
||||||
|
}
|
||||||
|
return clamp(res,0.0,1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 render( in vec3 ro, in vec3 rd, in vec4 c )
|
||||||
|
{
|
||||||
|
vec3 light1 = vec3( 0.577, 0.577, 0.577 );
|
||||||
|
vec3 light2 = vec3( -0.707, 0.000, -0.707 );
|
||||||
|
|
||||||
|
vec4 tra;
|
||||||
|
vec3 col;
|
||||||
|
float t = intersect( ro, rd, tra, c );
|
||||||
|
if( t < 0.0 )
|
||||||
|
{
|
||||||
|
col = vec3(0.8,0.9,1.0)*(0.7+0.3*rd.y);
|
||||||
|
col += vec3(0.8,0.7,0.5)*pow( clamp(dot(rd,light1),0.0,1.0), 48.0 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
col = vec3(1.0,0.8,0.7)*0.3;
|
||||||
|
|
||||||
|
vec3 pos = ro + t*rd;
|
||||||
|
vec3 nor = calcNormal( pos, c );
|
||||||
|
vec3 ref = reflect( rd, nor );
|
||||||
|
|
||||||
|
float dif1 = clamp( dot( light1, nor ), 0.0, 1.0 );
|
||||||
|
float dif2 = clamp( 0.5 + 0.5*dot( light2, nor ), 0.0, 1.0 );
|
||||||
|
float occ = clamp(2.5*tra.w-0.15,0.0,1.0);
|
||||||
|
float sha = softshadow( pos, light1, 0.001, 64.0, c );
|
||||||
|
float fre = pow( clamp( 1.+dot(rd,nor), 0.0, 1.0 ), 2.0 );
|
||||||
|
|
||||||
|
vec3 lin = 1.5*vec3(0.15,0.20,0.25)*(0.6+0.4*nor.y)*(0.1+0.9*occ);
|
||||||
|
lin += 3.5*vec3(1.00,0.90,0.70)*dif1*sha;
|
||||||
|
lin += 1.5*vec3(0.14,0.14,0.14)*dif2*occ;
|
||||||
|
lin += 0.3*vec3(1.00,0.80,0.60)*fre*(0.5+0.5*occ);
|
||||||
|
|
||||||
|
col *= lin;
|
||||||
|
col += pow( clamp( dot( ref, light1 ), 0.0, 1.0 ), 32.0 )*dif1*sha;
|
||||||
|
col += 0.1*vec3(0.8,0.9,1.0)*smoothstep( 0.0, 0.1, ref.y )*occ*(0.5+0.5*nor.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pow( col, vec3(0.4545) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
// anim
|
||||||
|
float time = iGlobalTime*.15;
|
||||||
|
vec4 c = 0.4*cos( vec4(0.5,3.9,1.4,1.1) + time*vec4(1.2,1.7,1.3,2.5) ) - vec4(0.3,0.0,0.0,0.0);
|
||||||
|
|
||||||
|
// camera
|
||||||
|
float r = 1.4+0.15*cos(0.0+0.29*time);
|
||||||
|
vec3 ro = vec3( r*cos(0.3+0.37*time),
|
||||||
|
0.3 + 0.8*r*cos(1.0+0.33*time),
|
||||||
|
r*cos(2.2+0.31*time) );
|
||||||
|
vec3 ta = vec3(0.0,0.0,0.0);
|
||||||
|
float cr = 0.1*cos(0.1*time);
|
||||||
|
|
||||||
|
|
||||||
|
// render
|
||||||
|
vec3 col = vec3(0.0);
|
||||||
|
for( int j=0; j<AA; j++ )
|
||||||
|
for( int i=0; i<AA; i++ )
|
||||||
|
{
|
||||||
|
vec2 p = (-iResolution.xy + 2.0*(fragCoord + vec2(float(i),float(j))/float(AA))) / iResolution.y;
|
||||||
|
|
||||||
|
vec3 cw = normalize(ta-ro);
|
||||||
|
vec3 cp = vec3(sin(cr), cos(cr),0.0);
|
||||||
|
vec3 cu = normalize(cross(cw,cp));
|
||||||
|
vec3 cv = normalize(cross(cu,cw));
|
||||||
|
vec3 rd = normalize( p.x*cu + p.y*cv + 2.0*cw );
|
||||||
|
|
||||||
|
col += render( ro, rd, c );
|
||||||
|
}
|
||||||
|
col /= float(AA*AA);
|
||||||
|
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
col *= 0.7 + 0.3*pow(16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y),0.25);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
330
procedural/nrx-voxel-pacman.slang
Normal file
330
procedural/nrx-voxel-pacman.slang
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
#version 450
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// GGGG IIIII AAA N N TTTTT PPPP AAA CCCC M M AAA N N //
|
||||||
|
// G I A A NN N T P P A A C MM MM A A NN N //
|
||||||
|
// G GG I AAAAA N N N T PPPP AAAAA C --- M M M AAAAA N N N //
|
||||||
|
// G G I A A N NN T P A A C M M A A N NN //
|
||||||
|
// GGGG IIIII A A N N T P A A CCCC M M A A N N //
|
||||||
|
// //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Parameters
|
||||||
|
#define VOXEL_RESOLUTION 1.5
|
||||||
|
#define VOXEL_LIGHTING
|
||||||
|
#define SHADOW
|
||||||
|
#define GROUND
|
||||||
|
#define GHOST
|
||||||
|
//#define MOUSE
|
||||||
|
#define HSV2RGB_FAST
|
||||||
|
|
||||||
|
#define CAMERA_FOCAL_LENGTH 2.0
|
||||||
|
#define DELTA 0.01
|
||||||
|
#define RAY_LENGTH_MAX 500.0
|
||||||
|
#define RAY_STEP_MAX 100.0
|
||||||
|
#define AMBIENT 0.2
|
||||||
|
#define SPECULAR_POWER 2.0
|
||||||
|
#define SPECULAR_INTENSITY 0.3
|
||||||
|
#define SHADOW_LENGTH 150.0
|
||||||
|
#define SHADOW_POWER 3.0
|
||||||
|
#define FADE_POWER 1.0
|
||||||
|
#define BACKGROUND 0.7
|
||||||
|
#define GLOW 0.4
|
||||||
|
#define GAMMA 0.8
|
||||||
|
|
||||||
|
// Math constants
|
||||||
|
#define PI 3.14159265359
|
||||||
|
#define SQRT3 1.73205080757
|
||||||
|
|
||||||
|
// Global variable to handle the glow effect
|
||||||
|
float glowCounter;
|
||||||
|
|
||||||
|
// PRNG (from https://www.shadertoy.com/view/4djSRW)
|
||||||
|
float rand (in vec3 seed) {
|
||||||
|
seed = fract (seed * vec3 (5.3983, 5.4427, 6.9371));
|
||||||
|
seed += dot (seed.yzx, seed.xyz + vec3 (21.5351, 14.3137, 15.3219));
|
||||||
|
return fract (seed.x * seed.y * seed.z * 95.4337);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distance to the voxel
|
||||||
|
float distVoxel (in vec3 p) {
|
||||||
|
|
||||||
|
// Update the glow counter
|
||||||
|
++glowCounter;
|
||||||
|
|
||||||
|
// Rounded box
|
||||||
|
const float voxelRadius = 0.25;
|
||||||
|
return length (max (abs (p) - 0.5 + voxelRadius, 0.0)) - voxelRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distance to the scene and color of the closest point
|
||||||
|
vec2 distScene (in vec3 p, out vec3 P) {
|
||||||
|
|
||||||
|
// Update the glow counter
|
||||||
|
++glowCounter;
|
||||||
|
|
||||||
|
// Scaling
|
||||||
|
p *= VOXEL_RESOLUTION;
|
||||||
|
|
||||||
|
// Velocity, period of the waves, spacing of the gums
|
||||||
|
float v = VOXEL_RESOLUTION * floor (iGlobalTime * 100.0 / VOXEL_RESOLUTION);
|
||||||
|
const float k1 = 0.05;
|
||||||
|
const float k2 = 60.0;
|
||||||
|
|
||||||
|
// Giant Pac-Man
|
||||||
|
float body = length (p);
|
||||||
|
body = max (body - 32.0, 27.0 - body);
|
||||||
|
float eyes = 6.0 - length (vec3 (abs (p.x) - 12.5, p.y - 19.5, p.z - 20.0));
|
||||||
|
float mouthAngle = PI * (0.07 + 0.07 * cos (2.0 * v * PI / k2));
|
||||||
|
float mouthTop = dot (p, vec3 (0.0, -cos (mouthAngle), sin (mouthAngle))) - 2.0;
|
||||||
|
mouthAngle *= 2.5;
|
||||||
|
float mouthBottom = dot (p, vec3 (0.0, cos (mouthAngle), sin (mouthAngle)));
|
||||||
|
float pacMan = max (max (body, eyes), min (mouthTop, mouthBottom));
|
||||||
|
vec2 d = vec2 (pacMan, 0.13);
|
||||||
|
P = p;
|
||||||
|
|
||||||
|
// Gums
|
||||||
|
vec3 q = vec3 (p.xy, mod (p.z + v, k2) - k2 * 0.5);
|
||||||
|
float gum = max (length (q) - 6.0, -p.z);
|
||||||
|
if (gum < d.x) {
|
||||||
|
d = vec2 (gum, 0.35);
|
||||||
|
P = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ground
|
||||||
|
#ifdef GROUND
|
||||||
|
q = vec3 (p.xy, p.z + v);
|
||||||
|
float ground = (q.y + 50.0 + 14.0 * cos (q.x * k1) * cos (q.z * k1)) * 0.7;
|
||||||
|
if (ground < d.x) {
|
||||||
|
d = vec2 (ground, 0.55);
|
||||||
|
P = q;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Ghost
|
||||||
|
#ifdef GHOST
|
||||||
|
v = VOXEL_RESOLUTION * floor ((130.0 + 60.0 * cos (iGlobalTime * 3.0)) / VOXEL_RESOLUTION);
|
||||||
|
q = vec3 (p.xy, p.z + v);
|
||||||
|
body = length (vec3 (q.x, max (q.y - 4.0, 0.0), q.z));
|
||||||
|
body = max (body - 28.0, 22.0 - body);
|
||||||
|
eyes = 8.0 - length (vec3 (abs (q.x) - 12.0, q.y - 10.0, q.z - 22.0));
|
||||||
|
float bottom = (q.y + 28.0 + 4.0 * cos (p.x * 0.4) * cos (p.z * 0.4)) * 0.7;
|
||||||
|
float ghost = max (max (body, eyes), -bottom);
|
||||||
|
if (ghost < d.x) {
|
||||||
|
d = vec2 (ghost, 0.76);
|
||||||
|
P = q;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Scaling
|
||||||
|
d.x /= VOXEL_RESOLUTION;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distance to the (voxelized?) scene
|
||||||
|
vec4 dist (inout vec3 p, in vec3 ray, in float voxelized, in float rayLengthMax) {
|
||||||
|
vec3 P = p;
|
||||||
|
vec2 d = vec2 (0.0, 0.0);
|
||||||
|
float rayLength = 0.0;
|
||||||
|
float rayLengthInVoxel = 0.0;
|
||||||
|
float rayLengthCheckVoxel = 0.0;
|
||||||
|
vec3 raySign = sign (ray);
|
||||||
|
vec3 rayDeltaVoxel = raySign / ray;
|
||||||
|
for (float rayStep = 0.0; rayStep < RAY_STEP_MAX; ++rayStep) {
|
||||||
|
if (rayLength < rayLengthInVoxel) {
|
||||||
|
d.x = distVoxel (fract (p + 0.5) - 0.5);
|
||||||
|
if (d.x < DELTA) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (rayLength < rayLengthCheckVoxel) {
|
||||||
|
vec3 rayDelta = (0.5 - raySign * (fract (p + 0.5) - 0.5)) * rayDeltaVoxel;
|
||||||
|
float dNext = min (rayDelta.x, min (rayDelta.y, rayDelta.z));
|
||||||
|
d = distScene (floor (p + 0.5), P);
|
||||||
|
if (d.x < 0.0) {
|
||||||
|
rayDelta = rayDeltaVoxel - rayDelta;
|
||||||
|
d.x = max (rayLengthInVoxel - rayLength, DELTA - min (rayDelta.x, min (rayDelta.y, rayDelta.z)));
|
||||||
|
rayLengthInVoxel = rayLength + dNext;
|
||||||
|
} else {
|
||||||
|
d.x = DELTA + dNext;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d = distScene (p, P);
|
||||||
|
if (voxelized > 0.5) {
|
||||||
|
if (d.x < SQRT3 * 0.5) {
|
||||||
|
rayLengthCheckVoxel = rayLength + abs (d.x) + SQRT3 * 0.5;
|
||||||
|
d.x = max (rayLengthInVoxel - rayLength + DELTA, d.x - SQRT3 * 0.5);
|
||||||
|
}
|
||||||
|
} else if (d.x < DELTA) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rayLength += d.x;
|
||||||
|
if (rayLength > rayLengthMax) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p += d.x * ray;
|
||||||
|
}
|
||||||
|
return vec4 (d, rayLength, rand (P));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal at a given point
|
||||||
|
vec3 normal (in vec3 p, in float voxelized) {
|
||||||
|
vec2 h = vec2 (DELTA, -DELTA);
|
||||||
|
vec3 n;
|
||||||
|
if (voxelized > 0.5) {
|
||||||
|
p = fract (p + 0.5) - 0.5;
|
||||||
|
n = h.xxx * distVoxel (p + h.xxx) +
|
||||||
|
h.xyy * distVoxel (p + h.xyy) +
|
||||||
|
h.yxy * distVoxel (p + h.yxy) +
|
||||||
|
h.yyx * distVoxel (p + h.yyx);
|
||||||
|
} else {
|
||||||
|
n = h.xxx * distScene (p + h.xxx, n).x +
|
||||||
|
h.xyy * distScene (p + h.xyy, n).x +
|
||||||
|
h.yxy * distScene (p + h.yxy, n).x +
|
||||||
|
h.yyx * distScene (p + h.yyx, n).x;
|
||||||
|
}
|
||||||
|
return normalize (n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HSV to RGB
|
||||||
|
vec3 hsv2rgb (in vec3 hsv) {
|
||||||
|
#ifdef HSV2RGB_SAFE
|
||||||
|
hsv.yz = clamp (hsv.yz, 0.0, 1.0);
|
||||||
|
#endif
|
||||||
|
#ifdef HSV2RGB_FAST
|
||||||
|
return hsv.z * (1.0 + 0.5 * hsv.y * (cos (2.0 * PI * (hsv.x + vec3 (0.0, 2.0 / 3.0, 1.0 / 3.0))) - 1.0));
|
||||||
|
#else
|
||||||
|
return hsv.z * (1.0 + hsv.y * clamp (abs (fract (hsv.x + vec3 (0.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - 3.0) - 2.0, -1.0, 0.0));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main function
|
||||||
|
void mainImage (out vec4 fragColor, in vec2 fragCoord) {
|
||||||
|
|
||||||
|
// Get the fragment
|
||||||
|
vec2 frag = (2.0 * fragCoord.xy - iResolution.xy) / iResolution.y;
|
||||||
|
|
||||||
|
// Define the rendering mode
|
||||||
|
float modeTiming = iGlobalTime * 0.234;
|
||||||
|
float modeAngle = PI * cos (iGlobalTime * 0.2);
|
||||||
|
modeAngle = dot (frag - vec2 (cos (iGlobalTime * 2.0), 0.0), vec2 (cos (modeAngle), sin (modeAngle)));
|
||||||
|
float modeVoxel = step (0.5, fract (modeTiming / (4.0 * PI)));
|
||||||
|
modeTiming = cos (modeTiming);
|
||||||
|
float mode3D = smoothstep (0.8, 0.5, modeTiming);
|
||||||
|
float modeSwitch = smoothstep (0.995, 1.0, modeTiming) + smoothstep (0.02, 0.0, abs (modeAngle)) * (1.0 - modeVoxel);
|
||||||
|
modeVoxel += step (0.0, modeAngle) * (1.0 - modeVoxel);
|
||||||
|
|
||||||
|
// Define the ray corresponding to this fragment
|
||||||
|
vec3 ray = normalize (vec3 (frag, mix (8.0, CAMERA_FOCAL_LENGTH, mode3D)));
|
||||||
|
|
||||||
|
// Compute the orientation of the camera
|
||||||
|
float yawAngle = PI * (1.2 + 0.2 * cos (iGlobalTime * 0.5));
|
||||||
|
float pitchAngle = PI * (0.1 * cos (iGlobalTime * 0.3) - 0.05);
|
||||||
|
#ifdef MOUSE
|
||||||
|
yawAngle += 4.0 * PI * iMouse.x / iResolution.x;
|
||||||
|
pitchAngle += PI * 0.3 * (1.0 - iMouse.y / iResolution.y);
|
||||||
|
#endif
|
||||||
|
yawAngle = mix (PI * 1.5, yawAngle, mode3D);
|
||||||
|
pitchAngle *= mode3D;
|
||||||
|
|
||||||
|
float cosYaw = cos (yawAngle);
|
||||||
|
float sinYaw = sin (yawAngle);
|
||||||
|
float cosPitch = cos (pitchAngle);
|
||||||
|
float sinPitch = sin (pitchAngle);
|
||||||
|
|
||||||
|
mat3 cameraOrientation;
|
||||||
|
cameraOrientation [0] = vec3 (cosYaw, 0.0, -sinYaw);
|
||||||
|
cameraOrientation [1] = vec3 (sinYaw * sinPitch, cosPitch, cosYaw * sinPitch);
|
||||||
|
cameraOrientation [2] = vec3 (sinYaw * cosPitch, -sinPitch, cosYaw * cosPitch);
|
||||||
|
|
||||||
|
ray = cameraOrientation * ray;
|
||||||
|
|
||||||
|
// Compute the origin of the ray
|
||||||
|
float cameraDist = mix (300.0, 95.0 + 50.0 * cos (iGlobalTime * 0.8), mode3D);
|
||||||
|
vec3 origin = (vec3 (0.0, 0.0, 40.0 * sin (iGlobalTime * 0.2)) - cameraOrientation [2] * cameraDist) / VOXEL_RESOLUTION;
|
||||||
|
|
||||||
|
// Compute the distance to the scene
|
||||||
|
glowCounter = 0.0;
|
||||||
|
vec4 d = dist (origin, ray, modeVoxel, RAY_LENGTH_MAX / VOXEL_RESOLUTION);
|
||||||
|
|
||||||
|
// Set the background color
|
||||||
|
vec3 finalColor = hsv2rgb (vec3 (0.2 * ray.y + 0.4 * modeVoxel - 0.37, 1.0, mode3D * BACKGROUND));
|
||||||
|
vec3 glowColor = GLOW * vec3 (1.0, 0.3, 0.0) * glowCounter / RAY_STEP_MAX;
|
||||||
|
if (d.x < DELTA) {
|
||||||
|
|
||||||
|
// Set the object color
|
||||||
|
vec3 color = hsv2rgb (vec3 (d.y + 0.1 * d.w * modeVoxel, 0.5 + 0.5 * modeVoxel, 1.0));
|
||||||
|
|
||||||
|
// Lighting
|
||||||
|
vec3 l = normalize (mix (vec3 (1.0, 0.0, 0.0), vec3 (1.25 + cos (iGlobalTime * 0.2), 1.0, 1.0), mode3D));
|
||||||
|
#ifdef VOXEL_LIGHTING
|
||||||
|
if (modeVoxel > 0.5) {
|
||||||
|
vec3 n = normal (floor (origin + 0.5), 0.0);
|
||||||
|
float diffuse = max (0.0, dot (n, l));
|
||||||
|
float specular = pow (max (0.0, dot (reflect (ray, n), l)), SPECULAR_POWER) * SPECULAR_INTENSITY;
|
||||||
|
color = (AMBIENT + diffuse) * color + specular;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
vec3 n = normal (origin, modeVoxel);
|
||||||
|
float diffuse = dot (n, l);
|
||||||
|
float specular;
|
||||||
|
if (diffuse < 0.0) {
|
||||||
|
diffuse = 0.0;
|
||||||
|
specular = 0.0;
|
||||||
|
} else {
|
||||||
|
specular = pow (max (0.0, dot (reflect (ray, n), l)), SPECULAR_POWER) * SPECULAR_INTENSITY;
|
||||||
|
#ifdef SHADOW
|
||||||
|
origin += n * DELTA * 2.0;
|
||||||
|
vec4 shadow = dist (origin, l, modeVoxel, SHADOW_LENGTH / VOXEL_RESOLUTION);
|
||||||
|
if (shadow.x < DELTA) {
|
||||||
|
shadow.z = pow (min (1.0, shadow.z * VOXEL_RESOLUTION / SHADOW_LENGTH), SHADOW_POWER);
|
||||||
|
diffuse *= shadow.z;
|
||||||
|
specular *= shadow.z;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
color = (AMBIENT + diffuse) * color + specular;
|
||||||
|
|
||||||
|
// Fading
|
||||||
|
float fade = pow (max (0.0, 1.0 - d.z * VOXEL_RESOLUTION / RAY_LENGTH_MAX), FADE_POWER);
|
||||||
|
finalColor = mix (finalColor, color, fade);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the fragment color
|
||||||
|
finalColor = mix (pow (finalColor, vec3 (GAMMA)) + glowColor, vec3 (1.0), modeSwitch);
|
||||||
|
fragColor = vec4 (finalColor, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
281
procedural/reinder-alotofspheres.slang
Normal file
281
procedural/reinder-alotofspheres.slang
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
#version 450
|
||||||
|
// A lot of spheres. Created by Reinder Nijhoff 2013
|
||||||
|
// @reindernijhoff
|
||||||
|
//
|
||||||
|
// https://www.shadertoy.com/view/lsX3WH
|
||||||
|
//
|
||||||
|
|
||||||
|
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 SHADOW
|
||||||
|
#define REFLECTION
|
||||||
|
|
||||||
|
|
||||||
|
#define RAYCASTSTEPS 40
|
||||||
|
|
||||||
|
#define EXPOSURE 0.9
|
||||||
|
#define EPSILON 0.0001
|
||||||
|
#define MAXDISTANCE 400.
|
||||||
|
#define GRIDSIZE 8.
|
||||||
|
#define GRIDSIZESMALL 5.
|
||||||
|
#define MAXHEIGHT 10.
|
||||||
|
#define SPEED 0.5
|
||||||
|
|
||||||
|
#define time iGlobalTime
|
||||||
|
|
||||||
|
//
|
||||||
|
// math functions
|
||||||
|
//
|
||||||
|
|
||||||
|
const mat2 mr = mat2 (0.84147, 0.54030,
|
||||||
|
0.54030, -0.84147 );
|
||||||
|
float hash( float n ) {
|
||||||
|
return fract(sin(n)*43758.5453);
|
||||||
|
}
|
||||||
|
vec2 hash2( float n ) {
|
||||||
|
return fract(sin(vec2(n,n+1.0))*vec2(2.1459123,3.3490423));
|
||||||
|
}
|
||||||
|
vec2 hash2( vec2 n ) {
|
||||||
|
return fract(sin(vec2( n.x*n.y, n.x+n.y))*vec2(2.1459123,3.3490423));
|
||||||
|
}
|
||||||
|
vec3 hash3( float n ) {
|
||||||
|
return fract(sin(vec3(n,n+1.0,n+2.0))*vec3(3.5453123,4.1459123,1.3490423));
|
||||||
|
}
|
||||||
|
vec3 hash3( vec2 n ) {
|
||||||
|
return fract(sin(vec3(n.x, n.y, n+2.0))*vec3(3.5453123,4.1459123,1.3490423));
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// intersection functions
|
||||||
|
//
|
||||||
|
|
||||||
|
bool intersectPlane(vec3 ro, vec3 rd, float height, out float dist) {
|
||||||
|
if (rd.y==0.0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float d = -(ro.y - height)/rd.y;
|
||||||
|
d = min(100000.0, d);
|
||||||
|
if( d > 0. ) {
|
||||||
|
dist = d;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersectUnitSphere ( in vec3 ro, in vec3 rd, in vec3 sph, out float dist, out vec3 normal ) {
|
||||||
|
vec3 ds = ro - sph;
|
||||||
|
float bs = dot( rd, ds );
|
||||||
|
float cs = dot( ds, ds ) - 1.0;
|
||||||
|
float ts = bs*bs - cs;
|
||||||
|
|
||||||
|
if( ts > 0.0 ) {
|
||||||
|
ts = -bs - sqrt( ts );
|
||||||
|
if( ts>0. ) {
|
||||||
|
normal = normalize( (ro+ts*rd)-sph );
|
||||||
|
dist = ts;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Scene
|
||||||
|
//
|
||||||
|
|
||||||
|
void getSphereOffset( vec2 grid, inout vec2 center ) {
|
||||||
|
center = (hash2( grid+vec2(43.12,1.23) ) - vec2(0.5) )*(GRIDSIZESMALL);
|
||||||
|
}
|
||||||
|
void getMovingSpherePosition( vec2 grid, vec2 sphereOffset, inout vec3 center ) {
|
||||||
|
// falling?
|
||||||
|
float s = 0.1+hash( grid.x*1.23114+5.342+754.324231*grid.y );
|
||||||
|
float t = 14.*s + time/s;
|
||||||
|
|
||||||
|
float y = s * MAXHEIGHT * abs( cos( t ) );
|
||||||
|
vec2 offset = grid + sphereOffset;
|
||||||
|
|
||||||
|
center = vec3( offset.x, y, offset.y ) + 0.5*vec3( GRIDSIZE, 2., GRIDSIZE );
|
||||||
|
}
|
||||||
|
void getSpherePosition( vec2 grid, vec2 sphereOffset, inout vec3 center ) {
|
||||||
|
vec2 offset = grid + sphereOffset;
|
||||||
|
center = vec3( offset.x, 0., offset.y ) + 0.5*vec3( GRIDSIZE, 2., GRIDSIZE );
|
||||||
|
}
|
||||||
|
vec3 getSphereColor( vec2 grid ) {
|
||||||
|
return normalize( hash3( grid+vec2(43.12*grid.y,12.23*grid.x) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 trace(vec3 ro, vec3 rd, out vec3 intersection, out vec3 normal, out float dist, out int material) {
|
||||||
|
material = 0; // sky
|
||||||
|
dist = MAXDISTANCE;
|
||||||
|
float distcheck;
|
||||||
|
|
||||||
|
vec3 sphereCenter, col, normalcheck;
|
||||||
|
|
||||||
|
if( intersectPlane( ro, rd, 0., distcheck) && distcheck < MAXDISTANCE ) {
|
||||||
|
dist = distcheck;
|
||||||
|
material = 1;
|
||||||
|
normal = vec3( 0., 1., 0. );
|
||||||
|
col = vec3( 1. );
|
||||||
|
} else {
|
||||||
|
col = vec3( 0. );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// trace grid
|
||||||
|
vec3 pos = floor(ro/GRIDSIZE)*GRIDSIZE;
|
||||||
|
vec3 ri = 1.0/rd;
|
||||||
|
vec3 rs = sign(rd) * GRIDSIZE;
|
||||||
|
vec3 dis = (pos-ro + 0.5 * GRIDSIZE + rs*0.5) * ri;
|
||||||
|
vec3 mm = vec3(0.0);
|
||||||
|
vec2 offset;
|
||||||
|
|
||||||
|
for( int i=0; i<RAYCASTSTEPS; i++ ) {
|
||||||
|
if( material > 1 || distance( ro.xz, pos.xz ) > dist+GRIDSIZE ) break;
|
||||||
|
vec2 offset;
|
||||||
|
getSphereOffset( pos.xz, offset );
|
||||||
|
|
||||||
|
getMovingSpherePosition( pos.xz, -offset, sphereCenter );
|
||||||
|
|
||||||
|
if( intersectUnitSphere( ro, rd, sphereCenter, distcheck, normalcheck ) && distcheck < dist ) {
|
||||||
|
dist = distcheck;
|
||||||
|
normal = normalcheck;
|
||||||
|
material = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSpherePosition( pos.xz, offset, sphereCenter );
|
||||||
|
if( intersectUnitSphere( ro, rd, sphereCenter, distcheck, normalcheck ) && distcheck < dist ) {
|
||||||
|
dist = distcheck;
|
||||||
|
normal = normalcheck;
|
||||||
|
col = vec3( 2. );
|
||||||
|
material = 3;
|
||||||
|
}
|
||||||
|
mm = step(dis.xyz, dis.zyx);
|
||||||
|
dis += mm * rs * ri;
|
||||||
|
pos += mm * rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 color = vec3( 0. );
|
||||||
|
if( material > 0 ) {
|
||||||
|
intersection = ro + rd*dist;
|
||||||
|
vec2 map = floor(intersection.xz/GRIDSIZE)*GRIDSIZE;
|
||||||
|
|
||||||
|
if( material == 1 || material == 3 ) {
|
||||||
|
// lightning
|
||||||
|
vec3 c = vec3( -GRIDSIZE,0., GRIDSIZE );
|
||||||
|
for( int x=0; x<3; x++ ) {
|
||||||
|
for( int y=0; y<3; y++ ) {
|
||||||
|
vec2 mapoffset = map+vec2( c[x], c[y] );
|
||||||
|
vec2 offset;
|
||||||
|
getSphereOffset( mapoffset, offset );
|
||||||
|
vec3 lcolor = getSphereColor( mapoffset );
|
||||||
|
vec3 lpos;
|
||||||
|
getMovingSpherePosition( mapoffset, -offset, lpos );
|
||||||
|
|
||||||
|
float shadow = 1.;
|
||||||
|
#ifdef SHADOW
|
||||||
|
if( material == 1 ) {
|
||||||
|
for( int sx=0; sx<3; sx++ ) {
|
||||||
|
for( int sy=0; sy<3; sy++ ) {
|
||||||
|
if( shadow < 1. ) continue;
|
||||||
|
|
||||||
|
vec2 smapoffset = map+vec2( c[sx], c[sy] );
|
||||||
|
vec2 soffset;
|
||||||
|
getSphereOffset( smapoffset, soffset );
|
||||||
|
vec3 slpos, sn;
|
||||||
|
getSpherePosition( smapoffset, soffset, slpos );
|
||||||
|
float sd;
|
||||||
|
if( intersectUnitSphere( intersection, normalize( lpos - intersection ), slpos, sd, sn ) ) {
|
||||||
|
shadow = 0.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
color += col * lcolor * ( shadow * max( dot( normalize(lpos-intersection), normal ), 0.) *
|
||||||
|
(1. - clamp( distance( lpos, intersection )/GRIDSIZE, 0., 1.) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// emitter
|
||||||
|
color = (1.5+dot(normal, vec3( 0.5, 0.5, -0.5) )) *getSphereColor( map );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// camera
|
||||||
|
vec3 ce = vec3( cos( 0.232*time) * 10., 6.+3.*cos(0.3*time), GRIDSIZE*(time/SPEED) );
|
||||||
|
vec3 ro = ce;
|
||||||
|
vec3 ta = ro + vec3( -sin( 0.232*time) * 10., -2.0+cos(0.23*time), 10.0 );
|
||||||
|
|
||||||
|
float roll = -0.15*sin(0.5*time);
|
||||||
|
|
||||||
|
// camera tx
|
||||||
|
vec3 cw = normalize( ta-ro );
|
||||||
|
vec3 cp = vec3( sin(roll), cos(roll),0.0 );
|
||||||
|
vec3 cu = normalize( cross(cw,cp) );
|
||||||
|
vec3 cv = normalize( cross(cu,cw) );
|
||||||
|
vec3 rd = normalize( p.x*cu + p.y*cv + 1.5*cw );
|
||||||
|
|
||||||
|
// raytrace
|
||||||
|
int material;
|
||||||
|
vec3 normal, intersection;
|
||||||
|
float dist;
|
||||||
|
|
||||||
|
vec3 col = trace(ro, rd, intersection, normal, dist, material);
|
||||||
|
|
||||||
|
#ifdef REFLECTION
|
||||||
|
if( material > 0 ) {
|
||||||
|
vec3 ro = intersection + EPSILON*normal;
|
||||||
|
rd = reflect( rd, normal );
|
||||||
|
col += 0.05 * trace(ro, rd, intersection, normal, dist, material);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
col = pow( col, vec3(EXPOSURE, EXPOSURE, EXPOSURE) );
|
||||||
|
col = clamp(col, 0.0, 1.0);
|
||||||
|
|
||||||
|
// vigneting
|
||||||
|
col *= 0.25+0.75*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.15 );
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
403
procedural/reinder-tokyo.slang
Normal file
403
procedural/reinder-tokyo.slang
Normal file
|
@ -0,0 +1,403 @@
|
||||||
|
#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);
|
||||||
|
}
|
|
@ -464,7 +464,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
//just some shit to wrap shadertoy's stuff
|
//just some shit to wrap shadertoy's stuff
|
||||||
vec2 FragCoord = vTexCoord.xy*global.OutputSize.xy;
|
vec2 FragmentCoord = vTexCoord.xy*global.OutputSize.xy;
|
||||||
FragCoord.y = -FragCoord.y;
|
FragmentCoord.y = -FragmentCoord.y;
|
||||||
mainImage(FragColor,FragCoord);
|
mainImage(FragColor,FragmentCoord);
|
||||||
}
|
}
|
||||||
|
|
573
procedural/shane-fractal-flythrough.slang
Normal file
573
procedural/shane-fractal-flythrough.slang
Normal file
|
@ -0,0 +1,573 @@
|
||||||
|
#version 450
|
||||||
|
/*
|
||||||
|
Quasi Infinite Zoom Voronoi
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The infinite zoom effect has been keeping me amused for years.
|
||||||
|
|
||||||
|
This one is based on something I wrote some time ago, but was inspired by Fabrice Neyret's
|
||||||
|
"Infinite Fall" shader. I've aired on the side of caution and called it "quasi infinite,"
|
||||||
|
just in case it doesn't adhere to his strict infinite zoom standards. :)
|
||||||
|
|
||||||
|
Seriously though, I put together a couple of overly optimized versions a couple of days ago,
|
||||||
|
just for fun, and Fabrice's comments were pretty helpful. I also liked the way he did the
|
||||||
|
layer rotation in his "Infinite Fall" version, so I'm using that. The rest is stock standard
|
||||||
|
infinite zoom stuff that has been around for years.
|
||||||
|
|
||||||
|
Most people like to use noise for this effect, so I figured I'd do something different
|
||||||
|
and use Voronoi. I've also bump mapped it, added specular highlights, etc. It was
|
||||||
|
tempting to add a heap of other things, but I wanted to keep the example relatively simple.
|
||||||
|
|
||||||
|
By the way, most of the code is basic bump mapping and lighting. The infinite zoom code
|
||||||
|
takes up just a small portion.
|
||||||
|
|
||||||
|
|
||||||
|
Fabrice Neyret's versions:
|
||||||
|
|
||||||
|
infinite fall - short
|
||||||
|
https://www.shadertoy.com/view/ltjXWW
|
||||||
|
|
||||||
|
infinite fall - FabriceNeyret2
|
||||||
|
https://www.shadertoy.com/view/4sl3RX
|
||||||
|
|
||||||
|
Other examples:
|
||||||
|
|
||||||
|
Fractal Noise - mu6k
|
||||||
|
https://www.shadertoy.com/view/Msf3Wr
|
||||||
|
|
||||||
|
Infinite Sierpinski - gleurop
|
||||||
|
https://www.shadertoy.com/view/MdfGR8
|
||||||
|
|
||||||
|
Infinite Zoom - fizzer
|
||||||
|
https://www.shadertoy.com/view/MlXGW7
|
||||||
|
|
||||||
|
Private link to a textured version of this.
|
||||||
|
Bumped Infinite Zoom Texture - Shane
|
||||||
|
https://www.shadertoy.com/view/Xl2XWw
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Fractal Flythrough
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Moving a camera through a fractal object. It's a work in progress.
|
||||||
|
|
||||||
|
I was looking at one of Dr2's shaders that involved moving a camera through a set of way points (set
|
||||||
|
out on the XZ plane), and thought it'd be cool to do a similar 3D version. The idea was to create a
|
||||||
|
repetitive kind of fractal object, give the open space nodes a set random direction, create some
|
||||||
|
spline points, then run a smooth camera through them. Simple... right? It always seems simple in my
|
||||||
|
head, but gets progressively harder when I try it in a shader. :)
|
||||||
|
|
||||||
|
I've run into that classic up-vector, camera flipping problem... At least, I think that's the problem?
|
||||||
|
Anyway, I'm hoping the solution is simple, and that someone reading this will be able to point me in
|
||||||
|
the right direction.
|
||||||
|
|
||||||
|
For now, I've set up a set of 16 random looping points that the camera seems reasonably comfortable
|
||||||
|
with. Just for the record, the general setup works nicely, until the camera loops back on itself in
|
||||||
|
the YZ plane. I'm guessing that increasing the number of way points may eradicate some of the
|
||||||
|
intermittent camera spinning, but I figured I'd leave things alone and treat it as a feature. :)
|
||||||
|
|
||||||
|
By the way, I was thankful to have Otavio Good's spline setup in his "Alien Beacon" shader as a
|
||||||
|
reference. On a side note, that particular shader is one of my all time favorites on this site.
|
||||||
|
|
||||||
|
The rendering materials are slightly inspired by the Steampunk genre. Timber, granite, brass, etc.
|
||||||
|
It needs spinning turbines, gears, rivots, and so forth, but that stuff's expensive. Maybe later.
|
||||||
|
Tambako Jaguar did a really cool shader in the Steampunk aesthetic. The link is below.
|
||||||
|
|
||||||
|
Besides camera path, there's a whole bunch of improvements I'd like to make to this. I've relied on
|
||||||
|
occlusion to mask the fact that there are no shadows. I'm hoping to free up some cycles, so I can put
|
||||||
|
them back in. I'd also like to add extra detail, but that also slows things down. As for the comments,
|
||||||
|
they're very rushed, but I'll tidy those up as well.
|
||||||
|
|
||||||
|
References:
|
||||||
|
|
||||||
|
Alien Beacon - Otavio Good
|
||||||
|
https://www.shadertoy.com/view/ld2SzK
|
||||||
|
|
||||||
|
Steampunk Turbine - TambakoJaguar
|
||||||
|
https://www.shadertoy.com/view/lsd3zf
|
||||||
|
|
||||||
|
// The main inspiration for this shader.
|
||||||
|
Mandelmaze in Daylight - dr2
|
||||||
|
https://www.shadertoy.com/view/MdVGRc
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const float FAR = 50.0; // Far plane.
|
||||||
|
|
||||||
|
// Used to identify individual scene objects. In this case, there are only three: The metal framework, the gold
|
||||||
|
// and the timber.
|
||||||
|
float objID = 0.; // Wood = 1., Metal = 2., Gold = 3..
|
||||||
|
|
||||||
|
// Simple hash function.
|
||||||
|
float hash( float n ){ return fract(cos(n)*45758.5453); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Tri-Planar blending function. Based on an old Nvidia writeup:
|
||||||
|
// GPU Gems 3 - Ryan Geiss: https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch01.html
|
||||||
|
vec3 tex3D(sampler2D t, in vec3 p, in vec3 n ){
|
||||||
|
|
||||||
|
n = max(abs(n), 0.001);
|
||||||
|
n /= dot(n, vec3(1));
|
||||||
|
vec3 tx = texture(t, p.yz).xyz;
|
||||||
|
vec3 ty = texture(t, p.zx).xyz;
|
||||||
|
vec3 tz = texture(t, p.xy).xyz;
|
||||||
|
|
||||||
|
// Textures are stored in sRGB (I think), so you have to convert them to linear space
|
||||||
|
// (squaring is a rough approximation) prior to working with them... or something like that. :)
|
||||||
|
// Once the final color value is gamma corrected, you should see correct looking colors.
|
||||||
|
return (tx*tx*n.x + ty*ty*n.y + tz*tz*n.z);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common formula for rounded squares, for all intended purposes.
|
||||||
|
float lengthN(in vec2 p, in float n){ p = pow(abs(p), vec2(n)); return pow(p.x + p.y, 1.0/n); }
|
||||||
|
|
||||||
|
|
||||||
|
// The camera path: There are a few spline setups on Shadertoy, but this one is a slight variation of
|
||||||
|
// Otavio Good's spline setup in his "Alien Beacon" shader: https://www.shadertoy.com/view/ld2SzK
|
||||||
|
//
|
||||||
|
// Spline point markers ("cp" for camera point). The camera visits each point in succession, then loops
|
||||||
|
// back to the first point, when complete, in order to repeat the process. In case it isn't obvious, each
|
||||||
|
// point represents an open space juncture in the object that links to the previous and next point.
|
||||||
|
// Of course, running a camera in a straight line between points wouldn't produce a smooth camera effect,
|
||||||
|
// so we apply the Catmull-Rom equation to the line segment.
|
||||||
|
vec3 cp[16];
|
||||||
|
|
||||||
|
void setCamPath(){
|
||||||
|
|
||||||
|
// The larger fractal object has nodes in a 4x4x4 grid.
|
||||||
|
// The smaller one in a 2x2x2 grid. The following points
|
||||||
|
// map a path to various open areas throughout the object.
|
||||||
|
const float sl = 2.*.96;
|
||||||
|
const float bl = 4.*.96;
|
||||||
|
|
||||||
|
cp[0] = vec3(0, 0, 0);
|
||||||
|
cp[1] = vec3(0, 0, bl);
|
||||||
|
cp[2] = vec3(sl, 0, bl);
|
||||||
|
cp[3] = vec3(sl, 0, sl);
|
||||||
|
cp[4] = vec3(sl, sl, sl);
|
||||||
|
cp[5] = vec3(-sl, sl, sl);
|
||||||
|
cp[6] = vec3(-sl, 0, sl);
|
||||||
|
cp[7] = vec3(-sl, 0, 0);
|
||||||
|
|
||||||
|
cp[8] = vec3(0, 0, 0);
|
||||||
|
cp[9] = vec3(0, 0, -bl);
|
||||||
|
cp[10] = vec3(0, bl, -bl);
|
||||||
|
cp[11] = vec3(-sl, bl, -bl);
|
||||||
|
cp[12] = vec3(-sl, 0, -bl);
|
||||||
|
cp[13] = vec3(-sl, 0, 0);
|
||||||
|
cp[14] = vec3(-sl, -sl, 0);
|
||||||
|
cp[15] = vec3(0, -sl, 0);
|
||||||
|
|
||||||
|
// Tighening the radius a little, so that the camera doesn't hit the walls.
|
||||||
|
// I should probably hardcode this into the above... Done.
|
||||||
|
//for(int i=0; i<16; i++) cp[i] *= .96;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard Catmull-Rom equation. The equation takes in the line segment end points (p1 and p2), the
|
||||||
|
// points on either side (p0 and p3), the current fractional distance (t) along the segment, then
|
||||||
|
// returns the the smooth (cubic interpolated) position. The end result is a smooth transition
|
||||||
|
// between points... Look up a diagram on the internet. That should make it clearer.
|
||||||
|
vec3 Catmull(vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t){
|
||||||
|
|
||||||
|
return (((-p0 + p1*3. - p2*3. + p3)*t*t*t + (p0*2. - p1*5. + p2*4. - p3)*t*t + (-p0 + p2)*t + p1*2.)*.5);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Camera path. Determine the segment number (segNum), and how far - timewise - we are along it (segTime).
|
||||||
|
// Feed the segment, the appropriate adjoining segments, and the segment time into the Catmull-Rom
|
||||||
|
// equation to produce a camera position. The process is pretty simple, once you get the hang of it.
|
||||||
|
vec3 camPath(float t){
|
||||||
|
|
||||||
|
const int aNum = 16;
|
||||||
|
|
||||||
|
t = fract(t/float(aNum))*float(aNum); // Repeat every 16 time units.
|
||||||
|
|
||||||
|
// Segment number. Range: [0, 15], in this case.
|
||||||
|
float segNum = floor(t);
|
||||||
|
// Segment portion. Analogous to how far we are alone the individual line segment. Range: [0, 1].
|
||||||
|
float segTime = t - segNum;
|
||||||
|
|
||||||
|
|
||||||
|
if (segNum == 0.) return Catmull(cp[aNum-1], cp[0], cp[1], cp[2], segTime);
|
||||||
|
|
||||||
|
for(int i=1; i<aNum-2; i++){
|
||||||
|
if (segNum == float(i)) return Catmull(cp[i-1], cp[i], cp[i+1], cp[i+2], segTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segNum == float(aNum-2)) return Catmull(cp[aNum-3], cp[aNum-2], cp[aNum-1], cp[0], segTime);
|
||||||
|
if (segNum == float(aNum-1)) return Catmull(cp[aNum-2], cp[aNum-1], cp[0], cp[1], segTime);
|
||||||
|
|
||||||
|
return vec3(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smooth minimum function. There are countless articles, but IQ explains it best here:
|
||||||
|
// http://iquilezles.org/www/articles/smin/smin.htm
|
||||||
|
float sminP( float a, float b, float s ){
|
||||||
|
|
||||||
|
float h = clamp( 0.5+0.5*(b-a)/s, 0.0, 1.0 );
|
||||||
|
return mix( b, a, h ) - s*h*(1.0-h);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating the scene geometry.
|
||||||
|
//
|
||||||
|
// There are two intertwined fractal objects. One is a gold and timber lattice, spread out in a 4x4x4
|
||||||
|
// grid. The second is some metallic tubing spread out over a 2x2x2 grid. Each are created by combining
|
||||||
|
// repeat objects with various operations. All of it is pretty standard.
|
||||||
|
//
|
||||||
|
// The code is a little fused together, in order to save some cycles, but if you're interested in the
|
||||||
|
// process, I have a "Menger Tunnel" example that's a little easier to decipher.
|
||||||
|
float map(in vec3 q){
|
||||||
|
|
||||||
|
|
||||||
|
///////////
|
||||||
|
|
||||||
|
// The grey section. I have another Menger example, if you'd like to look into that more closely.
|
||||||
|
// Layer one.
|
||||||
|
vec3 p = abs(fract(q/4.)*4. - 2.);
|
||||||
|
float tube = min(max(p.x, p.y), min(max(p.y, p.z), max(p.x, p.z))) - 4./3. - .015;// + .05;
|
||||||
|
|
||||||
|
|
||||||
|
// Layer two.
|
||||||
|
p = abs(fract(q/2.)*2. - 1.);
|
||||||
|
//d = max(d, min(max(p.x, p.y), min(max(p.y, p.z), max(p.x, p.z))) - s/3.);// + .025
|
||||||
|
tube = max(tube, sminP(max(p.x, p.y), sminP(max(p.y, p.z), max(p.x, p.z), .05), .05) - 2./3.);// + .025
|
||||||
|
|
||||||
|
///////
|
||||||
|
// The gold and timber paneling.
|
||||||
|
//
|
||||||
|
// A bit of paneling, using a combination of repeat objects. We're doing it here in layer two, just
|
||||||
|
// to save an extra "fract" call. Very messy, but saves a few cycles... maybe.
|
||||||
|
|
||||||
|
//float panel = sminP(length(p.xy),sminP(length(p.yz),length(p.xz), 0.25), 0.125)-0.45; // EQN 1
|
||||||
|
//float panel = sqrt(min(dot(p.xy, p.xy),min(dot(p.yz, p.yz),dot(p.xz, p.xz))))-0.5; // EQN 2
|
||||||
|
//float panel = min(max(p.x, p.y),min(max(p.y, p.z),max(p.x, p.z)))-0.5; // EQN 3
|
||||||
|
float panel = sminP(max(p.x, p.y),sminP(max(p.y, p.z),max(p.x, p.z), .125), .125)-0.5; // EQN 3
|
||||||
|
|
||||||
|
|
||||||
|
// Gold strip. Probably not the best way to do this, but it gets the job done.
|
||||||
|
// Identifying the gold strip region, then edging it out a little... for whatever reason. :)
|
||||||
|
float strip = step(p.x, .75)*step(p.y, .75)*step(p.z, .75);
|
||||||
|
panel -= (strip)*.025;
|
||||||
|
|
||||||
|
// Timber bulge. Just another weird variation.
|
||||||
|
//float bulge = (max(max(p.x, p.y), p.z) - .55);//length(p)-1.;//
|
||||||
|
//panel -= bulge*(1.-step(p.x, .75)*step(p.y, .75)*step(p.z, .75))*bulge*.25;
|
||||||
|
|
||||||
|
// Repeat field entity two, which is just an abstract object repeated every half unit.
|
||||||
|
p = abs(fract(q*2.)*.5 - .25);
|
||||||
|
float pan2 = min(p.x, min(p.y,p.z))-.05;
|
||||||
|
|
||||||
|
// Combining the two entities above.
|
||||||
|
panel = max(abs(panel), abs(pan2)) - .0425;
|
||||||
|
/////////
|
||||||
|
|
||||||
|
// Layer three. 3D space is divided by three.
|
||||||
|
p = abs(fract(q*1.5)/1.5 - 1./3.);
|
||||||
|
tube = max(tube, min(max(p.x, p.y), min(max(p.y, p.z), max(p.x, p.z))) - 2./9. + .025); // + .025
|
||||||
|
|
||||||
|
|
||||||
|
// Layer three. 3D space is divided by two, instead of three, to give some variance.
|
||||||
|
p = abs(fract(q*3.)/3. - 1./6.);
|
||||||
|
tube = max(tube, min(max(p.x, p.y), min(max(p.y, p.z), max(p.x, p.z))) - 1./9. - .035); //- .025
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Object ID: Equivalent to: if(tube<panel)objID=2; else objID = 1.; //etc.
|
||||||
|
//
|
||||||
|
// By the way, if you need to identify multiple objects, you're better off doing it in a seperate pass,
|
||||||
|
// after the raymarching function. Having multiple "if" statements in a distance field equation can
|
||||||
|
// slow things down considerably.
|
||||||
|
|
||||||
|
//objID = 2. - step(tube, panel) + step(panel, tube)*(strip);
|
||||||
|
objID = 1.+ step(tube, panel) + step(panel, tube)*(strip)*2.;
|
||||||
|
//objID = 1. + step(panel, tube)*(strip) + step(tube, panel)*2.;
|
||||||
|
|
||||||
|
|
||||||
|
return min(panel, tube);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float trace(in vec3 ro, in vec3 rd){
|
||||||
|
|
||||||
|
float t = 0.0, h;
|
||||||
|
for(int i = 0; i < 92; i++){
|
||||||
|
|
||||||
|
h = map(ro+rd*t);
|
||||||
|
// Note the "t*b + a" addition. Basically, we're putting less emphasis on accuracy, as
|
||||||
|
// "t" increases. It's a cheap trick that works in most situations... Not all, though.
|
||||||
|
if(abs(h)<0.001*(t*.25 + 1.) || t>FAR) break; // Alternative: 0.001*max(t*.25, 1.)
|
||||||
|
t += h*.8;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The reflections are pretty subtle, so not much effort is being put into them. Only eight iterations.
|
||||||
|
float refTrace(vec3 ro, vec3 rd){
|
||||||
|
|
||||||
|
float t = 0.0;
|
||||||
|
for(int i=0; i<16; i++){
|
||||||
|
float d = map(ro + rd*t);
|
||||||
|
if (d < 0.0025*(t*.25 + 1.) || t>FAR) break;
|
||||||
|
t += d;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Tetrahedral normal, to save a couple of "map" calls. Courtesy of IQ.
|
||||||
|
vec3 calcNormal(in vec3 p){
|
||||||
|
|
||||||
|
// Note the slightly increased sampling distance, to alleviate artifacts due to hit point inaccuracies.
|
||||||
|
vec2 e = vec2(0.0025, -0.0025);
|
||||||
|
return normalize(e.xyy * map(p + e.xyy) + e.yyx * map(p + e.yyx) + e.yxy * map(p + e.yxy) + e.xxx * map(p + e.xxx));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Standard normal function. It's not as fast as the tetrahedral calculation, but more symmetrical. Due to
|
||||||
|
// the intricacies of this particular scene, it's kind of needed to reduce jagged effects.
|
||||||
|
vec3 calcNormal(in vec3 p) {
|
||||||
|
const vec2 e = vec2(0.005, 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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// I keep a collection of occlusion routines... OK, that sounded really nerdy. :)
|
||||||
|
// Anyway, I like this one. I'm assuming it's based on IQ's original.
|
||||||
|
float calcAO(in vec3 pos, in vec3 nor)
|
||||||
|
{
|
||||||
|
float sca = 2.0, occ = 0.0;
|
||||||
|
for( int i=0; i<5; i++ ){
|
||||||
|
|
||||||
|
float hr = 0.01 + float(i)*0.5/4.0;
|
||||||
|
float dd = map(nor * hr + pos);
|
||||||
|
occ += (hr - dd)*sca;
|
||||||
|
sca *= 0.7;
|
||||||
|
}
|
||||||
|
return clamp( 1.0 - occ, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Texture bump mapping. Four tri-planar lookups, or 12 texture lookups in total. I tried to
|
||||||
|
// make it as concise as possible. Whether that translates to speed, or not, I couldn't say.
|
||||||
|
vec3 texBump( sampler2D tx, in vec3 p, in vec3 n, float bf){
|
||||||
|
|
||||||
|
const vec2 e = vec2(0.001, 0);
|
||||||
|
|
||||||
|
// Three gradient vectors rolled into a matrix, constructed with offset greyscale texture values.
|
||||||
|
mat3 m = mat3( tex3D(tx, p - e.xyy, n), tex3D(tx, p - e.yxy, n), tex3D(tx, p - e.yyx, n));
|
||||||
|
|
||||||
|
vec3 g = vec3(0.299, 0.587, 0.114)*m; // Converting to greyscale.
|
||||||
|
g = (g - dot(tex3D(tx, p , n), vec3(0.299, 0.587, 0.114)) )/e.x; g -= n*dot(n, g);
|
||||||
|
|
||||||
|
return normalize( n + g*bf ); // Bumped normal. "bf" - bump factor.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ){
|
||||||
|
|
||||||
|
|
||||||
|
// Screen coordinates.
|
||||||
|
vec2 u = (fragCoord - iResolution.xy*0.5)/iResolution.y;
|
||||||
|
|
||||||
|
float speed = iGlobalTime*0.35 + 8.;
|
||||||
|
|
||||||
|
// Initiate the camera path spline points. Kind of wasteful not making this global, but I wanted
|
||||||
|
// it self contained... for better or worse. I'm not really sure what the GPU would prefer.
|
||||||
|
setCamPath();
|
||||||
|
|
||||||
|
|
||||||
|
// Camera Setup.
|
||||||
|
vec3 ro = camPath(speed); // Camera position, doubling as the ray origin.
|
||||||
|
vec3 lk = camPath(speed + .5); // "Look At" position.
|
||||||
|
vec3 lp = camPath(speed + .5) + vec3(0, .25, 0); // Light position, somewhere near the moving camera.
|
||||||
|
|
||||||
|
|
||||||
|
// Using the above to produce the unit ray-direction vector.
|
||||||
|
float FOV = 1.57; // FOV - Field of view.
|
||||||
|
vec3 fwd = normalize(lk-ro);
|
||||||
|
vec3 rgt = normalize(vec3(fwd.z, 0, -fwd.x));
|
||||||
|
vec3 up = (cross(fwd, rgt));
|
||||||
|
|
||||||
|
// Unit direction ray.
|
||||||
|
vec3 rd = normalize(fwd + FOV*(u.x*rgt + u.y*up));
|
||||||
|
|
||||||
|
|
||||||
|
// Raymarch the scene.
|
||||||
|
float t = trace(ro, rd);
|
||||||
|
|
||||||
|
// Initialize the scene color.
|
||||||
|
vec3 col = vec3(0);
|
||||||
|
|
||||||
|
// Scene hit, so color the pixel. Technically, the object should always be hit, so it's tempting to
|
||||||
|
// remove this entire branch... but I'll leave it, for now.
|
||||||
|
if(t<FAR){
|
||||||
|
|
||||||
|
// This looks a little messy and haphazard, but it's really just some basic lighting, and application
|
||||||
|
// of the following material properties: Wood = 1., Metal = 2., Gold = 3..
|
||||||
|
|
||||||
|
float ts = 1.; // Texture scale.
|
||||||
|
|
||||||
|
// Global object ID. It needs to be saved just after the raymarching equation, since other "map" calls,
|
||||||
|
// like normal calculations will give incorrect results. Found that out the hard way. :)
|
||||||
|
float saveObjID = objID;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 pos = ro + rd*t; // Scene postion.
|
||||||
|
vec3 nor = calcNormal(pos); // Normal.
|
||||||
|
vec3 sNor = nor;
|
||||||
|
|
||||||
|
|
||||||
|
// Apply some subtle texture bump mapping to the panels and the metal tubing.
|
||||||
|
nor = texBump(iChannel0, pos*ts, nor, 0.002); // + step(saveObjID, 1.5)*0.002
|
||||||
|
|
||||||
|
// Reflected ray. Note that the normal is only half bumped. It's fake, but it helps
|
||||||
|
// taking some of the warping effect off of the reflections.
|
||||||
|
vec3 ref = reflect(rd, normalize(sNor*.5 + nor*.5));
|
||||||
|
|
||||||
|
|
||||||
|
col = tex3D(iChannel0, pos*ts, nor); // Texture pixel at the scene postion.
|
||||||
|
|
||||||
|
|
||||||
|
vec3 li = lp - pos; // Point light.
|
||||||
|
float lDist = max(length(li), .001); // Surface to light distance.
|
||||||
|
float atten = 1./(1.0 + lDist*0.125 + lDist*lDist*.05); // Light attenuation.
|
||||||
|
li /= lDist; // Normalizing the point light vector.
|
||||||
|
|
||||||
|
float occ = calcAO( pos, nor ); // Occlusion.
|
||||||
|
|
||||||
|
float dif = clamp(dot(nor, li), 0.0, 1.0); // Diffuse.
|
||||||
|
dif = pow(dif, 4.)*2.;
|
||||||
|
float spe = pow(max(dot(reflect(-li, nor), -rd), 0.), 8.); // Object specular.
|
||||||
|
float spe2 = spe*spe; // Global specular.
|
||||||
|
|
||||||
|
float refl = .35; // Reflection coefficient. Different for different materials.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Reflection color. Mostly fake.
|
||||||
|
// Cheap reflection: Not entirely accurate, but the reflections are pretty subtle, so not much
|
||||||
|
// effort is being put in.
|
||||||
|
float rt = refTrace(pos + ref*0.1, ref); // Raymarch from "sp" in the reflected direction.
|
||||||
|
float rSaveObjID = objID; // IDs change with reflection. Learned that the hard way. :)
|
||||||
|
vec3 rsp = pos + ref*rt; // Reflected surface hit point.
|
||||||
|
vec3 rsn = calcNormal(rsp); // Normal at the reflected surface. Too costly to bump reflections.
|
||||||
|
vec3 rCol = tex3D(iChannel0, rsp*ts, rsn); // Texel at "rsp."
|
||||||
|
vec3 rLi = lp-rsp;
|
||||||
|
float rlDist = max(length(rLi), 0.001);
|
||||||
|
rLi /= rlDist;
|
||||||
|
float rDiff = max(dot(rsn, rLi), 0.); // Diffuse light at "rsp."
|
||||||
|
rDiff = pow(rDiff, 4.)*2.;
|
||||||
|
float rAtten = 1./(1. + rlDist*0.125 + rlDist*rlDist*.05);
|
||||||
|
|
||||||
|
if(rSaveObjID>1.5 && rSaveObjID<2.5){
|
||||||
|
rCol = vec3(1)*dot(rCol, vec3(.299, .587, .114))*.7 + rCol*.15;//*.7+.2
|
||||||
|
//rDiff *= 1.35;
|
||||||
|
}
|
||||||
|
if(rSaveObjID>2.5){
|
||||||
|
//float rc = dot(rCol, vec3(.299, .587, .114));
|
||||||
|
vec3 rFire = pow(vec3(1.5, 1, 1)*rCol, vec3(8, 2, 1.5));//*.5+rc*.5;
|
||||||
|
rCol = min(mix(vec3(1.5, .9, .375), vec3(.75, .375, .3), rFire), 2.)*.5 + rCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
rCol *= (rDiff + .35)*rAtten; // Reflected color. Not accurate, but close enough.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Grey metal inner tubing.
|
||||||
|
if(saveObjID>1.5 && saveObjID<2.5){
|
||||||
|
|
||||||
|
// Grey out the limestone wall color.
|
||||||
|
col = vec3(1)*dot(col, vec3(.299, .587, .114))*.7 + col*.15;
|
||||||
|
|
||||||
|
refl = .5;
|
||||||
|
//dif *= 1.35;
|
||||||
|
//spe2 *= 1.35;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gold trimming properties. More effort should probably be put in here.
|
||||||
|
// I could just write "saveObjID == 3.," but I get a little paranoid where floats are concerned. :)
|
||||||
|
if(saveObjID>2.5){
|
||||||
|
|
||||||
|
// For the screen image, we're interested in the offset height and depth positions. Ie: pOffs.zy.
|
||||||
|
|
||||||
|
// Pixelized dot pattern shade.
|
||||||
|
//float c = dot(col, vec3(.299, .587, .114));
|
||||||
|
|
||||||
|
vec3 fire = pow(vec3(1.5, 1, 1)*col, vec3(8, 2, 1.5));//*.5+c*.5;
|
||||||
|
col = min(mix(vec3(1, .9, .375), vec3(.75, .375, .3), fire), 2.)*.5 + col;//
|
||||||
|
|
||||||
|
refl = .65;
|
||||||
|
//dif *= 1.5;
|
||||||
|
//spe2 *= 1.5;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Combining everything together to produce the scene color.
|
||||||
|
col = col*(dif + .35 + vec3(.35, .45, .5)*spe) + vec3(.7, .9, 1)*spe2 + rCol*refl;
|
||||||
|
col *= occ*atten; // Applying occlusion.
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Applying some very slight fog in the distance. This is technically an inside scene...
|
||||||
|
// Or is it underground... Who cares, it's just a shader. :)
|
||||||
|
col = mix(min(col, 1.), vec3(0), 1.-exp(-t*t/FAR/FAR*20.));//smoothstep(0., FAR-20., t)
|
||||||
|
//col = mix(min(col, 1.), vec3(0), smoothstep(0., FAR-35., t));//smoothstep(0., FAR-20., t)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Done.
|
||||||
|
fragColor = vec4(sqrt(max(col, 0.)), 1.0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
386
procedural/shane-raymarched-reflections.slang
Normal file
386
procedural/shane-raymarched-reflections.slang
Normal file
|
@ -0,0 +1,386 @@
|
||||||
|
#version 450
|
||||||
|
/*
|
||||||
|
Raymarched Reflections
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
A very basic demonstration of raymarching a distance field with reflections
|
||||||
|
and reasonably passable shadows. Definitely not cutting edge, but hopefully,
|
||||||
|
interesting to anyone who isn't quite familiar with the process.
|
||||||
|
|
||||||
|
Reflections are pretty easy: Raymarch to the hit point, then obtain the color
|
||||||
|
at that point. Continue on from the hit point in the direction of the reflected
|
||||||
|
ray until you reach a new hit point. Obtain the color at the new point, then
|
||||||
|
add a portion of it to your original color. Repeat the process.
|
||||||
|
|
||||||
|
Unfortunately, the extra work can slow things down, especially when you apply
|
||||||
|
shadows, which is probably why you don't see too many shadowed, reflected
|
||||||
|
examples. However, for relatively simple distance fields, it's pretty doable.
|
||||||
|
|
||||||
|
It was tempting to do this up, but I figured a simpler example would be more
|
||||||
|
helpful. Take away the rambling comments, and there isn't a great deal of code.
|
||||||
|
I'll post a more sophisticated one later.
|
||||||
|
|
||||||
|
// Reasonably simple examples featuring reflection:
|
||||||
|
|
||||||
|
To the road of ribbon - XT95
|
||||||
|
https://www.shadertoy.com/view/MsfGzr
|
||||||
|
|
||||||
|
704.2 - PauloFalcao
|
||||||
|
https://www.shadertoy.com/view/Xdj3Dt
|
||||||
|
|
||||||
|
// Reflections and refraction. Really cool.
|
||||||
|
Glass Polyhedron - Nrx
|
||||||
|
https://www.shadertoy.com/view/4slSzj
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Raymarched Reflections
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
A very basic demonstration of raymarching a distance field with reflections
|
||||||
|
and reasonably passable shadows. Definitely not cutting edge, but hopefully,
|
||||||
|
interesting to anyone who isn't quite familiar with the process.
|
||||||
|
|
||||||
|
Reflections are pretty easy: Raymarch to the hit point, then obtain the color
|
||||||
|
at that point. Continue on from the hit point in the direction of the reflected
|
||||||
|
ray until you reach a new hit point. Obtain the color at the new point, then
|
||||||
|
add a portion of it to your original color. Repeat the process.
|
||||||
|
|
||||||
|
Unfortunately, the extra work can slow things down, especially when you apply
|
||||||
|
shadows, which is probably why you don't see too many shadowed, reflected
|
||||||
|
examples. However, for relatively simple distance fields, it's pretty doable.
|
||||||
|
|
||||||
|
It was tempting to do this up, but I figured a simpler example would be more
|
||||||
|
helpful. Take away the rambling comments, and there isn't a great deal of code.
|
||||||
|
I'll post a more sophisticated one later.
|
||||||
|
|
||||||
|
// Reasonably simple examples featuring reflection:
|
||||||
|
|
||||||
|
To the road of ribbon - XT95
|
||||||
|
https://www.shadertoy.com/view/MsfGzr
|
||||||
|
|
||||||
|
704.2 - PauloFalcao
|
||||||
|
https://www.shadertoy.com/view/Xdj3Dt
|
||||||
|
|
||||||
|
// Reflections and refraction. Really cool.
|
||||||
|
Glass Polyhedron - Nrx
|
||||||
|
https://www.shadertoy.com/view/4slSzj
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FAR 30.
|
||||||
|
|
||||||
|
// Distance function. This one is pretty simple. I chose rounded
|
||||||
|
// spherical boxes, because they're cheap and they display the
|
||||||
|
// reflections reasonably well.
|
||||||
|
float map(vec3 p)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Positioning the rounded cubes a little off center, in order
|
||||||
|
// to break up the space a little.
|
||||||
|
//
|
||||||
|
// "floor(p)" represents a unique number (ID) for each cube
|
||||||
|
// (based on its unique position). Take that number and produce
|
||||||
|
// a randomized 3D offset, then add it to it's regular position.
|
||||||
|
// Simple.
|
||||||
|
float n = sin(dot(floor(p), vec3(7, 157, 113)));
|
||||||
|
vec3 rnd = fract(vec3(2097152, 262144, 32768)*n)*.16-.08;
|
||||||
|
|
||||||
|
// Repeat factor. If irregularity isn't your thing, you can get
|
||||||
|
// rid of "rnd" to line things up again.
|
||||||
|
p = fract(p + rnd) - .5;
|
||||||
|
|
||||||
|
|
||||||
|
// Rounded spherical boxes. The following is made up, but kind of
|
||||||
|
// makes sense. Box, minus a bit of sphericalness, gives you a
|
||||||
|
// rounded box.
|
||||||
|
p = abs(p);
|
||||||
|
return max(p.x, max(p.y, p.z)) - 0.25 + dot(p, p)*0.5;
|
||||||
|
|
||||||
|
//return length(p) - 0.225; // Just spheres.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard raymarching routine.
|
||||||
|
float trace(vec3 ro, vec3 rd){
|
||||||
|
|
||||||
|
float t = 0., d;
|
||||||
|
|
||||||
|
for (int i = 0; i < 96; i++){
|
||||||
|
|
||||||
|
d = map(ro + rd*t);
|
||||||
|
|
||||||
|
if(abs(d)<.002 || t>FAR) break; // Normally just "d<.0025"
|
||||||
|
|
||||||
|
t += d*.75; // Using more accuracy, in the first pass.
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second pass, which is the first, and only, reflected bounce.
|
||||||
|
// Virtually the same as above, but with fewer iterations and less
|
||||||
|
// accuracy.
|
||||||
|
//
|
||||||
|
// The reason for a second, virtually identical equation is that
|
||||||
|
// raymarching is usually a pretty expensive exercise, so since the
|
||||||
|
// reflected ray doesn't require as much detail, you can relax things
|
||||||
|
// a bit - in the hope of speeding things up a little.
|
||||||
|
float traceRef(vec3 ro, vec3 rd){
|
||||||
|
|
||||||
|
float t = 0., d;
|
||||||
|
|
||||||
|
for (int i = 0; i < 48; i++){
|
||||||
|
|
||||||
|
d = map(ro + rd*t);
|
||||||
|
|
||||||
|
if(abs(d)<.0025 || t>FAR) break;
|
||||||
|
|
||||||
|
t += d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Cheap shadows are hard. In fact, I'd almost say, shadowing repeat objects - in a setting like this - with limited
|
||||||
|
// iterations is impossible... However, I'd be very grateful if someone could prove me wrong. :)
|
||||||
|
float softShadow(vec3 ro, vec3 lp, float k){
|
||||||
|
|
||||||
|
// More would be nicer. More is always nicer, but not really affordable... Not on my slow test machine, anyway.
|
||||||
|
const int maxIterationsShad = 24;
|
||||||
|
|
||||||
|
vec3 rd = (lp-ro); // Unnormalized direction ray.
|
||||||
|
|
||||||
|
float shade = 1.;
|
||||||
|
float dist = .005;
|
||||||
|
float end = max(length(rd), 0.001);
|
||||||
|
float stepDist = end/float(maxIterationsShad);
|
||||||
|
|
||||||
|
rd /= end;
|
||||||
|
|
||||||
|
// Max shadow iterations - More iterations make nicer shadows, but slow things down. Obviously, the lowest
|
||||||
|
// number to give a decent shadow is the best one to choose.
|
||||||
|
for (int i=0; i<maxIterationsShad; i++){
|
||||||
|
|
||||||
|
float h = map(ro + rd*dist);
|
||||||
|
//shade = min(shade, k*h/dist);
|
||||||
|
shade = min(shade, smoothstep(0.0, 1.0, k*h/dist)); // Subtle difference. Thanks to IQ for this tidbit.
|
||||||
|
// So many options here, and none are perfect: dist += min(h, .2), dist += clamp(h, .01, .2),
|
||||||
|
// clamp(h, .02, stepDist*2.), etc.
|
||||||
|
dist += clamp(h, .02, .2);
|
||||||
|
|
||||||
|
// Early exits from accumulative distance function calls tend to be a good thing.
|
||||||
|
if (h<0.0 || dist > end) break;
|
||||||
|
//if (h<0.001 || dist > end) break; // If you're prepared to put up with more artifacts.
|
||||||
|
}
|
||||||
|
|
||||||
|
// I've added 0.5 to the final shade value, which lightens the shadow a bit. It's a preference thing.
|
||||||
|
// Really dark shadows look too brutal to me.
|
||||||
|
return min(max(shade, 0.) + 0.25, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Standard normal function. It's not as fast as the tetrahedral calculation, but more symmetrical. Due to
|
||||||
|
// the intricacies of this particular scene, it's kind of needed to reduce jagged effects.
|
||||||
|
vec3 getNormal(in vec3 p) {
|
||||||
|
const vec2 e = vec2(0.002, 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)));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Tetrahedral normal, to save a couple of "map" calls. Courtesy of IQ.
|
||||||
|
vec3 getNormal( in vec3 p ){
|
||||||
|
|
||||||
|
// Note the slightly increased sampling distance, to alleviate
|
||||||
|
// artifacts due to hit point inaccuracies.
|
||||||
|
vec2 e = vec2(0.0035, -0.0035);
|
||||||
|
return normalize(
|
||||||
|
e.xyy * map(p + e.xyy) +
|
||||||
|
e.yyx * map(p + e.yyx) +
|
||||||
|
e.yxy * map(p + e.yxy) +
|
||||||
|
e.xxx * map(p + e.xxx));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alternating the cube colors in a 3D checkered arrangement.
|
||||||
|
// You could just return a single color, if you wanted, but I
|
||||||
|
// thought I'd mix things up a bit.
|
||||||
|
//
|
||||||
|
// Color scheme mildly influenced by: Sound Experiment 3 - aiekick
|
||||||
|
// https://www.shadertoy.com/view/Ml2XWt
|
||||||
|
vec3 getObjectColor(vec3 p){
|
||||||
|
|
||||||
|
vec3 col = vec3(1);
|
||||||
|
|
||||||
|
// "floor(p)" is analogous to a unique ID - based on position.
|
||||||
|
// This could be stepped, but it's more intuitive this way.
|
||||||
|
if(fract(dot(floor(p), vec3(.5))) > 0.001) col = vec3(0.6, 0.3, 1.0);
|
||||||
|
|
||||||
|
return col;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using the hit point, unit direction ray, etc, to color the
|
||||||
|
// scene. Diffuse, specular, falloff, etc. It's all pretty
|
||||||
|
// standard stuff.
|
||||||
|
vec3 doColor(in vec3 sp, in vec3 rd, in vec3 sn, in vec3 lp){
|
||||||
|
|
||||||
|
vec3 ld = lp-sp; // Light direction vector.
|
||||||
|
float lDist = max(length(ld), 0.001); // Light to surface distance.
|
||||||
|
ld /= lDist; // Normalizing the light vector.
|
||||||
|
|
||||||
|
// Attenuating the light, based on distance.
|
||||||
|
float atten = 1. / (1.0 + lDist*0.2 + lDist*lDist*0.1);
|
||||||
|
|
||||||
|
// Standard diffuse term.
|
||||||
|
float diff = max(dot(sn, ld), 0.);
|
||||||
|
// Standard specualr term.
|
||||||
|
float spec = pow(max( dot( reflect(-ld, sn), -rd ), 0.0 ), 8.0);
|
||||||
|
|
||||||
|
// Coloring the object. You could set it to a single color, to
|
||||||
|
// make things simpler, if you wanted.
|
||||||
|
vec3 objCol = getObjectColor(sp);
|
||||||
|
|
||||||
|
// Combining the above terms to produce the final scene color.
|
||||||
|
vec3 sceneCol = (objCol*(diff + 0.15) + vec3(1., .6, .2)*spec*2.) * atten;
|
||||||
|
|
||||||
|
|
||||||
|
// Return the color. Performed once every pass... of which there are
|
||||||
|
// only two, in this particular instance.
|
||||||
|
return sceneCol;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ){
|
||||||
|
|
||||||
|
// Screen coordinates.
|
||||||
|
vec2 uv = (fragCoord.xy - iResolution.xy*.5) / iResolution.y;
|
||||||
|
|
||||||
|
// Unit direction ray.
|
||||||
|
vec3 rd = normalize(vec3(uv, 1.0));
|
||||||
|
|
||||||
|
|
||||||
|
// Some cheap camera movement, for a bit of a look around. I use this far
|
||||||
|
// too often. I'm even beginning to bore myself, at this point. :)
|
||||||
|
float cs = cos(iGlobalTime * 0.25), si = sin(iGlobalTime * 0.25);
|
||||||
|
rd.xy = mat2(cs, si, -si, cs)*rd.xy;
|
||||||
|
rd.xz = mat2(cs, si, -si, cs)*rd.xz;
|
||||||
|
|
||||||
|
// Ray origin. Doubling as the surface position, in this particular example.
|
||||||
|
// I hope that doesn't confuse anyone.
|
||||||
|
vec3 ro = vec3(0., 0., iGlobalTime*1.5);
|
||||||
|
|
||||||
|
// Light position. Set in the vicinity the ray origin.
|
||||||
|
vec3 lp = ro + vec3(0., 1., -.5);
|
||||||
|
|
||||||
|
|
||||||
|
// FIRST PASS.
|
||||||
|
|
||||||
|
float t = trace(ro, rd);
|
||||||
|
|
||||||
|
// Fog based off of distance from the camera.
|
||||||
|
float fog = smoothstep(0., .95, t/FAR);
|
||||||
|
|
||||||
|
// Advancing the ray origin, "ro," to the new hit point.
|
||||||
|
ro += rd*t;
|
||||||
|
|
||||||
|
// Retrieving the normal at the hit point.
|
||||||
|
vec3 sn = getNormal(ro);
|
||||||
|
|
||||||
|
// Retrieving the color at the hit point, which is now "ro." I agree, reusing
|
||||||
|
// the ray origin to describe the surface hit point is kind of confusing. The reason
|
||||||
|
// we do it is because the reflective ray will begin from the hit point in the
|
||||||
|
// direction of the reflected ray. Thus the new ray origin will be the hit point.
|
||||||
|
// See "traceRef" below.
|
||||||
|
vec3 sceneColor = doColor(ro, rd, sn, lp);
|
||||||
|
|
||||||
|
// Checking to see if the surface is in shadow. Ideally, you'd also check to
|
||||||
|
// see if the reflected surface is in shadow. However, shadows are expensive, so
|
||||||
|
// it's only performed on the first pass. If you pause and check the reflections,
|
||||||
|
// you'll see that they're not shadowed. OMG! - Better call the shadow police. :)
|
||||||
|
float sh = softShadow(ro, lp, 16.);
|
||||||
|
|
||||||
|
|
||||||
|
// SECOND PASS - REFLECTED RAY
|
||||||
|
|
||||||
|
// Standard reflected ray, which is just a reflection of the unit
|
||||||
|
// direction ray off of the intersected surface. You use the normal
|
||||||
|
// at the surface point to do that. Hopefully, it's common sense.
|
||||||
|
rd = reflect(rd, sn);
|
||||||
|
|
||||||
|
|
||||||
|
// The reflected pass begins where the first ray ended, which is the suface
|
||||||
|
// hit point, or in a few cases, beyond the far plane. By the way, for the sake
|
||||||
|
// of simplicity, we'll perform a reflective pass for non hit points too. Kind
|
||||||
|
// of wasteful, but not really noticeable. The direction of the new ray will
|
||||||
|
// obviously be in the direction of the reflected ray. See just above.
|
||||||
|
//
|
||||||
|
// To anyone who's new to this, don't forgot to nudge the ray off of the
|
||||||
|
// initial surface point. Otherwise, you'll intersect with the surface
|
||||||
|
// you've just hit. After years of doing this, I still forget on occasion.
|
||||||
|
t = traceRef(ro + rd*.01, rd);
|
||||||
|
|
||||||
|
// Advancing the ray origin, "ro," to the new reflected hit point.
|
||||||
|
ro += rd*t;
|
||||||
|
|
||||||
|
// Retrieving the normal at the reflected hit point.
|
||||||
|
sn = getNormal(ro);
|
||||||
|
|
||||||
|
// Coloring the reflected hit point, then adding a portion of it to the final scene color.
|
||||||
|
// How much you add is up to you, but I'm going with 35 percent.
|
||||||
|
sceneColor += doColor(ro, rd, sn, lp)*.35;
|
||||||
|
|
||||||
|
|
||||||
|
// APPLYING SHADOWS
|
||||||
|
//
|
||||||
|
// Multiply the shadow from the first pass by the final scene color. Ideally, you'd check to
|
||||||
|
// see if the reflected point was in shadow, and incorporate that too, but we're cheating to
|
||||||
|
// save cycles and skipping it. It's not really noticeable anyway. By the way, ambient
|
||||||
|
// occlusion would make it a little nicer, but we're saving cycles and keeping things simple.
|
||||||
|
sceneColor *= sh;
|
||||||
|
|
||||||
|
// Technically, it should be applied on the reflection pass too, but it's not that
|
||||||
|
// noticeable, in this case.
|
||||||
|
sceneColor = mix(sceneColor, vec3(0), fog);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Clamping the scene color, performing some rough gamma correction (the "sqrt" bit), then
|
||||||
|
// presenting it to the screen.
|
||||||
|
fragColor = vec4(sqrt(clamp(sceneColor, 0.0, 1.0)), 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
Loading…
Reference in a new issue