mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-24 16:41:31 +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)
|
||||
{
|
||||
//just some shit to wrap shadertoy's stuff
|
||||
vec2 FragCoord = vTexCoord.xy*global.OutputSize.xy;
|
||||
FragCoord.y = -FragCoord.y;
|
||||
mainImage(FragColor,FragCoord);
|
||||
vec2 FragmentCoord = vTexCoord.xy*global.OutputSize.xy;
|
||||
FragmentCoord.y = -FragmentCoord.y;
|
||||
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