Add plethora of new shaders from shadertoy

This commit is contained in:
twinaphex 2018-02-23 18:44:56 +01:00
parent 7155843594
commit 06da9fcac8
11 changed files with 3529 additions and 3 deletions

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View file

@ -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);
}

View 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);
}

View 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);
}