💀 💀 💀
Log in to post a comment.
precision highp float;
uniform float iTime;
uniform vec2 iResolution;
uniform float rX;// value=0, min=-4, max=4, step=0.001
uniform float rY;// value=0, min=-4, max=4, step=0.001
uniform float rZ;// value=0, min=-4, max=4, step=0.001
uniform float bgType;// value=1, min=0, max=3, step=1 (Normal, Army of Skulls, Piter Plasma, Spiral)
uniform vec3 skin;// value=#FCFCFC
uniform vec3 background;// value=#347fcf
uniform float eyeDirection;// value=1, min=0, max=3, step=1 (Left, Up, Right, Down)
uniform float eyeType;// value=1, min=0, max=3, step=1 (Normal, Gradient, Piter Plasma, Spiral)
uniform vec3 eyeColor00;// value=#cd202c
uniform vec3 eyeColor01;// value=#cd202c
uniform vec3 eyeColor10;// value=#cd202c
uniform vec3 eyeColor11;// value=#cd202c
uniform float eyeY;// value=2, min=1, max=3, step=1
uniform float eyeHeight;// value=2, min=0, max=6, step=1
uniform float mouthType;// value=1, min=0, max=1, step=1 (One, Three)
uniform float mouthY;// value=9, min=4, max=10, step=1
uniform float mouthSize;// value=1, min=0, max=3, step=1
uniform float mouthWidth;// value=3, min=3, max=5, step=2
uniform float sideCheeksWidth;// value=2, min=1, max=10, step=1
uniform float sideCheeksHeight;// value=4, min=1, max=10, step=1
#define AA 2
#define PI 3.1415
#define m3 mat3(-0.7373, 0.4562, 0.4980, 0, -0.7373, 0.6754, 0.6754, 0.4980, 0.5437)
#define BLACK vec3(0)
const vec3 lightCol = vec3(1.3, 1., .8);
const vec3 skyCol = vec3( .4, .6,1.15);
const vec3 lightDir = normalize(vec3(-0.25, 0.4, -0.6));
vec2 eyeCoord;
mat3 rot;
//
// Hash functions by Dave Hoskins:
//
// https://www.shadertoy.com/view/4djSRW
//
float hash12(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * 443.8975);
p3 += dot(p3, p3.yzx + 19.19);
return fract((p3.x + p3.y) * p3.z);
}
vec3 hash33(vec3 p3) {
p3 = fract(p3 * vec3(443.897, 441.423, 437.195));
p3 += dot(p3, p3.yxz + 19.19);
return fract((p3.xxy + p3.yxx)*p3.zyx);
}
float noise(in vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
vec2 u = f*f*(3. -2.*f);
return mix(mix(hash12(i + vec2(0, 0)),
hash12(i + vec2(1, 0)), u.x),
mix(hash12(i + vec2(0, 1)),
hash12(i + vec2(1, 1)), u.x), u.y);
}
//
// rotation matrices
//
mat2 rot2D(float a) {
return mat2(cos(a), sin(a), -sin(a), cos(a));
}
mat3 rotX(float a) {
return mat3(
vec3(1, 0, 0),
vec3(0, cos(a), -sin(a)),
vec3(0, sin(a), cos(a))
);
}
mat3 rotY(float a) {
return mat3(
vec3(cos(a), 0, sin(a)),
vec3(0, 1, 0),
vec3(-sin(a), 0, cos(a))
);
}
mat3 rotZ(float a) {
return mat3(
vec3(cos(a), -sin(a), 0),
vec3(sin(a), cos(a), 0),
vec3(0, 0, 1)
);
}
//
// Background types
//
vec3 plasma(vec2 pos) {
vec3 p = vec3(pos * 2., iTime * 0.05);
float a = 1.;
vec3 n = vec3(0);
for (int i = 0; i <7; i++){
p = m3 * p;
vec3 s = sin(p.zxy / a) * a;
p += s * 2.;
n += s;
}
return n * 0.25 + 0.5;
}
vec3 spiral(vec2 uv, vec3 color) {
float r = length(uv);
float theta = atan(uv.y, uv.x);
return fract(theta * (2.5 / PI) + 7.0 * pow(r, 0.4) - iTime) < 0.5 ? color : vec3(0);
}
vec3 stripes(vec2 uv, vec3 color) {
return fract(uv.x * 4. + uv.y * 4. - .2 * iTime) < 0.5 ? color : vec3(0);
}
//
// SDF framework by Inigo Quilez:
//
// https://www.shadertoy.com/view/Xds3zN
//
// http://iquilezles.org/www/articles/smin/smin.htm
float smin(float a, float b, float k) {
float h = max(k-abs(a-b), 0.0)/k;
return min(a, b) - h*h*h*k*(1.0/6.0);
}
// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
float sdSphere(vec3 p, float s) {
return length(p)-s;
}
float sdBox(vec3 p, 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 sdPlane(vec3 p, vec3 n, float h) {
return dot(p, n) + h;
}
float sdRoundBox(vec3 p, vec3 b, float r) {
vec3 q = abs(p) - b + r;
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0) - r;
}
// http://iquilezles.org/www/articles/smin/smin.htm
vec2 opU(vec2 d1, vec2 d2) {
return (d1.x<d2.x) ? d1 : d2;
}
vec2 opS(vec2 d1, vec2 d2) {
return (-d1.x>d2.x) ? vec2(-d1.x, d1.y) : d2;
}
vec2 opI(vec2 d1, vec2 d2) {
return (d1.x>d2.x) ? d1 : d2;
}
vec2 map(in vec3 pos) {
if (bgType == 1.) {
pos = mod(pos + 25., 50.) - 25.;
}
pos = rot * pos;
pos.y -= sin(iTime) * .5;
const float featureDepth = 0.5;
const float featureRadius = 0.25;
vec3 apos = vec3(abs(pos.x), pos.y, pos.z);
// skull
vec2 d = vec2(sdRoundBox(pos, vec3(5.5), 1.), 0.);
d = opS(vec2(sdBox(apos - vec3(5.5, -5.5, 0), vec3(sideCheeksWidth, sideCheeksHeight, 7.5)), 0.), d);
d = opS(vec2(sdBox(pos - vec3(0., -5.5, 5.5), vec3(10., sideCheeksHeight, 6.)), 0.), d);
// mouth
if (mouthType < .5) { // single block
d = opS(vec2(sdRoundBox(apos - vec3(0, 5.5-mouthY-mouthSize+1., -5.5), vec3(mouthWidth * .5, mouthSize+1., featureDepth), featureRadius), 1.), d);
} else { // three blocks
d = opS(vec2(sdRoundBox(apos - vec3(0, 5.5-mouthY-mouthSize+1., -5.5), vec3(0.5, mouthSize+1., featureDepth), featureRadius), 1.), d);
d = opS(vec2(sdRoundBox(apos - vec3(2., 5.5-mouthY-mouthSize+1., -5.5), vec3(0.5, mouthSize+1., featureDepth), featureRadius), 1.), d);
}
// eyes
d = opS(vec2(sdRoundBox(apos - vec3(2., 5.5-eyeY-eyeHeight*.5-.5, -5.5), vec3(1.5, eyeHeight*.5+.5, featureDepth), featureRadius), 2.), d);
eyeCoord.y = apos.y - (4.5-eyeY-eyeHeight);
eyeCoord.x = mod(pos.x - .5, 4.) * sign(pos.x);
return d;
}
float calcSoftshadow(in vec3 ro, in vec3 rd, in float mint, in float tmax) {
float res = 1.0;
float t = mint;
float ph = 1e10;
for (int i=0; i<16; i++) {
float h = map(ro + rd*t).x;
float y = h*h/(2.0*ph);
float d = sqrt(h*h-y*y);
res = min(res, 10.0*d/max(0.0, t-y));
ph = h;
t += h;
if (res<0.0001 || t>tmax) break;
}
res = clamp(res, 0.0, 1.0);
return smoothstep(0., 1., res);// res*res*(3.0-2.0*res);
}
vec3 calcNormal(in vec3 pos) {
vec2 e = vec2(1.0, -1.0)*0.01;
return normalize(e.xyy*map(pos + e.xyy).x +
e.yyx*map(pos + e.yyx).x +
e.yxy*map(pos + e.yxy).x +
e.xxx*map(pos + e.xxx).x);
}
float calcAO(in vec3 pos, in vec3 nor) {
float occ = 0.;
float sca = 1.;
for (int i=0; i<5; i++) {
float hr = .005 + .12*float(i)/4.;
vec3 aopos = nor * hr + pos;
float dd = min(aopos.y, map(aopos).x);
occ += -(dd -hr)*sca;
sca *= .95;
}
return clamp(1. - 3.*occ, 0., 1.);
}
vec3 render(in vec3 ro, in vec3 rd) {
float t = 0.;
float tmax = 1000.;
float mat = -1.;
for (int i=0; i<100; i++) {
vec2 res = map(ro+rd*t);
if (abs(res.x) < max(0.001, .0005*t) || t > tmax) {
mat = t > tmax ? -1. : res.y;
break;
}
t += res.x;
}
// shade scene
vec3 bgCol = bgType == 2. ? plasma(rd.xy) : bgType == 3. ? spiral(rd.xy, background) : background;
bgCol *= bgCol;
vec3 col = bgCol;
if (mat >= 0.) {
vec3 pos = ro + t*rd;
vec3 nor = calcNormal(pos);
vec3 ref = reflect(rd, nor);
float eyeY = max(0., floor(eyeCoord.y));
float eyeX = max(0., floor(3. - abs(eyeCoord.x)));
bool left = eyeCoord.x > 0.;
vec3 eye = left ? eyeColor00 : eyeColor10;
if (eyeType == 0.) { // normal
}
else if (eyeType == 1.) { // gradient
if (eyeHeight > 0.) {
vec3 eye2 = left ? eyeColor01 : eyeColor11;
eye = mix(eye2 * eye2, eye * eye, (eyeY / eyeHeight));
eye = sqrt (eye);
}
}
else if (eyeType == 2.) { // plasma
eye = plasma(eyeCoord.xy * .1);
}
else if (eyeType == 3.) { // spiral
eye = spiral(abs(eyeCoord) - 1.5, eye);
}
if (eyeDirection == 0. && eyeX < .5) eye = BLACK;
else if (eyeDirection == 1. && eyeY > (eyeHeight - .5)) eye = BLACK;
else if (eyeDirection == 2. && eyeX > 1.5) eye = BLACK;
else if (eyeDirection == 3. && eyeY < .5) eye = BLACK;
col = (mat == 0. ? skin : mat == 1. ? BLACK : eye);
col *= col;
// lighting
// use three lights setup as made popular by Inigo Quilez
// sun
vec3 hal = normalize(lightDir-rd);
float difSun = max(dot(nor, lightDir), 0.);
difSun *= calcSoftshadow(pos, lightDir, 0.02, 2.5);
float specSun = pow(clamp(dot(nor, hal), 0., 1.), 16.) * difSun;
specSun *= 0.04+0.96*pow(clamp(1.0-dot(hal, lightDir), 0., 1.), 5.);
vec3 diff = (difSun)*lightCol;
vec3 spec = (2.5*specSun)*lightCol;
// sky
float difSky = sqrt(0.75+0.25*nor.y);
float specSky = smoothstep(-0.2, 0.2, ref.y) * difSky;
specSky *= 0.04+0.96*pow(clamp(1.0+dot(nor, rd), 0.0, 1.0), 5.0);
vec3 skyLight = bgType == 2. ? plasma(ref.xy) : skyCol;
diff += (0.3*difSky)*skyLight;
spec += specSky*skyLight;
// back light / ambient
float difBack = max(dot(nor, -lightDir), 0.);
diff += col*(0.08*difBack);
col = diff * col + spec;
// fog
col = mix(col, bgCol, clamp(1. - exp(-0.005*t) * 1.1, 0., 1.));
}
// cheap gamma correction
return sqrt(col);
}
mat3 setCamera(in vec3 ro, in vec3 ta) {
vec3 cw = normalize(ta -ro);
vec3 cu = normalize(cross(cw, vec3(0, 1, 0)));
vec3 cv = normalize(cross(cu, cw));
return mat3(cu, cv, cw);
}
void main() {
rot = rotZ(rZ) * rotX(rX + .25 * (noise(vec2(1.5, iTime * 0.5)) - .5)) * rotY(rY + .5 * (noise(vec2(2.5, iTime * 0.3)) - .5));
vec3 tot = vec3(0);
vec2 q = (gl_FragCoord.xy * 2. - iResolution.xy) / iResolution.y;
for (int m=0; m<AA; m++) {
for (int n=0; n<AA; n++) {
vec2 o = vec2(float(m), float(n))*(2./float(AA)) - .5;
// rotate AA offset to reduce aliasing
o *= rot2D(0.463647609);
vec2 p = q + o/iResolution.y;
vec3 ro = vec3(sin(iTime*.3), 0., -22.5);
vec3 ta = vec3(0., ro.y, 0.);
mat3 ca = setCamera(ro, ta);
vec3 rd = ca * normalize(vec3(p.xy, 2));
vec3 col = render(ro, rd);
tot += col;
}
}
tot *= (1./float(AA*AA));
// vigneting
q = gl_FragCoord.xy / iResolution.xy;
tot *= 0.25+0.75*pow(16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.15);
// noise
tot += vec3(hash12(gl_FragCoord.xy) * 0.02);
gl_FragColor = vec4(tot, 1.);
}