slang-shaders/procedural/fizzer-kirby-jump.slang

287 lines
6.4 KiB
Plaintext
Raw Normal View History

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