0.00
60.0 fps

💀

💀 💀 💀

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