Preview
precision highp float;
uniform vec2 resolution;
uniform vec2 mouse;
uniform float time;
uniform sampler2D backbuffer;
//--reference--
//https://wgld.org/
//https://iquilezles.org/articles/distfunctions/
//https://www.shadertoy.com/view/NtdXD4
//https://www.osar.fr/notes/logspherical/
//https://qiita.com/keim_at_si/items/c2d1afd6443f3040e900
//https://scrapbox.io/0b5vr/Plasma_Effect
//-------------
const int MAT_BODY = 0;
const int MAT_MOUTH = 1;
const int MAT_EYE_BALL = 2;
const int MAT_GAMING = 3;
const int MAT_DAIZA = 4;
struct MarchResult {
float dist;
int material;
};
vec3 hsv2rgb(float h, float s, float v) {
return ((clamp(abs(fract(h+vec3(0,2,1)/3.)*6.-3.)-1.,0.,1.)-1.)*s+1.)*v;
}
mat2 rot(float r) {
return mat2(cos(r), sin(r), -sin(r), cos(r));
}
float smoothUnion(float d1, float d2, float k) {
float h = clamp(0.5 + 0.5 * (d2 - d1)/k, 0.0, 1.0);
return mix(d2, d1, h) - k*h*(1.0-h);
}
float smoothSubtraction(float d1, float d2, float k) {
float h = clamp(0.5 - 0.5 * (d2+d1)/k, 0.0, 1.0);
return mix(d2, -d1, h) + k*h*(1.0-h);
}
float sdSphere(vec3 p, float r) {
return length(p) - r;
}
float sdBox(vec3 p, vec3 b)
{
vec3 q = abs(p) - b;
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
}
float sdHexPrism(vec3 p, vec2 h) {
vec3 k = vec3(-0.8660254, 0.5, 0.57735);
p = abs(p);
p.xy -= 2.0 * min(dot(k.xy, p.xy), 0.0) * k.xy;
vec2 d = vec2(
length(p.xy-vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x)) * sign(p.y-h.x),
p.z-h.y);
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
}
float sdCapsule(vec3 p, vec3 a, vec3 b, float r) {
vec3 pa = p - a, ba = b - a;
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
return length(pa - ba*h) - r;
}
float sdRoundCone(vec3 p, float r1, float r2, float h) {
float b = (r1-r2)/h;
float a = sqrt(1.0-b*b);
vec2 q = vec2(length(p.xz), p.y);
float k = dot(q, vec2(-b, a));
if(k<0.0) return length(q) - r1;
if(k>a*h) return length(q - vec2(0.0, h)) - r2;
return dot(q, vec2(a, b)) - r1;
}
float sdEye(vec3 p, float r) {
float d = sdSphere(p, r);
float d2 = sdSphere(p + vec3(0.0, -0.025, -r), r * 0.7);
float outer = smoothSubtraction(d2, d, 0.02);
return outer;
}
float sdMouth(vec3 p, float smile) {
float k = smile;
float c = cos(k*p.x);
float s = sin(k*p.x);
mat2 m = mat2(c, -s, s, c);
vec3 q = vec3(m*p.xy, p.z);
return sdCapsule(q, vec3(0.25, 0.0, 0.5), vec3(-0.25, 0.0, 0.5), 0.025);
}
vec2 footOffset1(float offset) {
return vec2(
min(sin(time*5.0 + offset) * -0.5, 0.18),
max(sin(time*5.0 + offset) * -0.5, -0.18)
);
}
vec2 footOffset2(float offset) {
return vec2(
abs(sin(time*5.0 + offset)) * 0.5 * clamp(sin(time*5.0 + offset), 0.0, 1.0),
abs(sin(time*5.0 + offset)) * 0.5 * clamp(sin(time*-5.0 - offset), 0.0, 1.0)
);
}
float sdFoot(vec3 p) {
vec3 offset = vec3(0.0, 0.4, 0.8);
float upperFootR1 = sdCapsule(p, vec3(0.7 + footOffset1(offset.x).x, -0.1 + footOffset2(offset.x).x, 0.0), vec3(1.0, -0.2 + footOffset2(offset.x).x, 0.0), 0.065);
float lowerFootR1 = sdCapsule(p, vec3(1.0, -0.2 + footOffset2(offset.x).x, 0.0), vec3(1.0, -0.5 + footOffset2(offset.x).x, 0.0), 0.065);
float footR1 = smoothUnion(upperFootR1, lowerFootR1, 0.025);
float upperFootR2 = sdCapsule(p, vec3(0.7 + footOffset1(offset.y).x, -0.1 + footOffset2(offset.y).x, 0.1), vec3(1.0, -0.2 + footOffset2(offset.y).x, 0.25), 0.065);
float lowerFootR2 = sdCapsule(p, vec3(1.0, -0.2 + footOffset2(offset.y).x, 0.25), vec3(1.0, -0.5 + footOffset2(offset.y).x, 0.25), 0.065);
float footR2 = smoothUnion(upperFootR2, lowerFootR2, 0.025);
float upperFootR3 = sdCapsule(p, vec3(0.7 + footOffset1(offset.z).x, -0.1 + footOffset2(offset.z).x, -0.1), vec3(1.0, -0.2 + footOffset2(offset.z).x, -0.25), 0.065);
float lowerFootR3 = sdCapsule(p, vec3(1.0, -0.2 + footOffset2(offset.z).x, -0.25), vec3(1.0, -0.5 + footOffset2(offset.z).x, -0.25), 0.065);
float footR3 = smoothUnion(upperFootR3, lowerFootR3, 0.025);
float upperFootL1 = sdCapsule(p, vec3(-0.7 + footOffset1(offset.x).y, -0.1 + footOffset2(offset.x).y, 0.0), vec3(-1.0, -0.2 + footOffset2(offset.x).y, 0.0), 0.065);
float lowerFootL1 = sdCapsule(p, vec3(-1.0, -0.2 + footOffset2(offset.x).y, 0.0), vec3(-1.0, -0.5 + footOffset2(offset.x).y, 0.0), 0.065);
float footL1 = smoothUnion(upperFootL1, lowerFootL1, 0.025);
float upperFootL2 = sdCapsule(p, vec3(-0.7 + footOffset1(offset.y).y, -0.1 + footOffset2(0.0).y, 0.1), vec3(-1.0, -0.2 + footOffset2(offset.y).y, 0.25), 0.065);
float lowerFootL2 = sdCapsule(p, vec3(-1.0, -0.2 + footOffset2(offset.y).y, 0.25), vec3(-1.0, -0.5 + footOffset2(offset.y).y , 0.25), 0.065);
float footL2 = smoothUnion(upperFootL2, lowerFootL2, 0.025);
float upperFootL3 = sdCapsule(p, vec3(-0.7 + footOffset1(offset.z).y, -0.1 + footOffset2(offset.z).y, -0.1), vec3(-1.0, -0.2 + footOffset2(offset.z).y, -0.25), 0.065);
float lowerFootL3 = sdCapsule(p, vec3(-1.0, -0.2 + footOffset2(offset.z).y, -0.25), vec3(-1.0, -0.5 + footOffset2(offset.z).y, -0.25), 0.065);
float footL3 = smoothUnion(upperFootL3, lowerFootL3, 0.025);
float footR = min(min(footR1, footR2), footR3);
float footL = min(min(footL1, footL2), footL3);
return min(footR, footL);
}
float sdEye(vec3 p) {
float eyeStickR = sdCapsule(p, vec3(0.2, 0.0, 0.0), vec3(0.2, 1.0, 0.0), 0.05);
float eyeStickL = sdCapsule(p, vec3(-0.2, 0.0, 0.0), vec3(-0.2, 1.0, 0.0), 0.05);
float eyeR = smoothUnion(eyeStickR, sdEye(p + vec3(-0.19, -1.0, 0.0), 0.15), 0.1);
float eyeL = smoothUnion(eyeStickL, sdEye(p + vec3(0.19, -1.0, 0.0), 0.15), 0.1);
return min(eyeR, eyeL);
}
float sdScissors(vec3 p, vec3 offset, float angle) {
vec3 p4arm = p + offset;
p4arm.xy *= rot(angle);
return sdRoundCone(p4arm, 0.1, 0.05, 0.3);
}
float sdArm(vec3 p) {
float armStickR = sdCapsule(p, vec3(0.5, 0.0, 0.0), vec3(0.9, 0.7, 0.0), 0.065);
float armStickL = sdCapsule(p, vec3(-0.5, 0.0, 0.0), vec3(-0.9, 0.7, 0.0), 0.065);
float scissorsR = smoothUnion(
sdScissors(p, vec3(-0.9, -0.75, 0.0), acos(-1.0)/4.0 * max(abs(sin(time * 5.0)), 0.3)),
sdScissors(p, vec3(-0.9, -0.75, 0.0), acos(-1.0)/-4.0 * max(abs(sin(time * 5.0)), 0.3)),
0.05
);
float scissorsL = smoothUnion(
sdScissors(p, vec3(0.9, -0.75, 0.0), acos(-1.0)/4.0 * max(abs(sin(time * 5.0 + acos(-1.0) / 2.0)), 0.3)),
sdScissors(p, vec3(0.9, -0.75, 0.0), acos(-1.0)/-4.0 * max(abs(sin(time * 5.0 + acos(-1.0) / 2.0)), 0.3)),
0.05
);
float armR = smoothUnion(armStickR, scissorsR, 0.1);
float armL = smoothUnion(armStickL, scissorsL, 0.1);
return min(armR, armL);
}
float sdO(vec3 p, float size) {
float s = size * 2.0;
float o1 = sdBox(p + vec3(0.0, -s*2.0, 0.0), vec3(size));
float o2 = sdBox(p + vec3(-s, -s*2.0, 0.0), vec3(size));
float o3 = sdBox(p + vec3(s, -s*2.0, 0.0), vec3(size));
float o4 = sdBox(p + vec3(-s*2.0, 0.0, 0.0), vec3(size));
float o5 = sdBox(p + vec3(-s*2.0, -s, 0.0), vec3(size));
float o6 = sdBox(p + vec3(-s*2.0, s, 0.0), vec3(size));
float o7 = sdBox(p + vec3(0.0, s*2.0, 0.0), vec3(size));
float o8 = sdBox(p + vec3(-s, s*2.0, 0.0), vec3(size));
float o9 = sdBox(p + vec3(s, s*2.0, 0.0), vec3(size));
float o10 = sdBox(p + vec3(s*2.0, 0.0, 0.0), vec3(size));
float o11 = sdBox(p + vec3(s*2.0, -s, 0.0), vec3(size));
float o12 = sdBox(p + vec3(s*2.0, s, 0.0), vec3(size));
float o123 = min(min(o1, o2), o3);
float o456 = min(min(o4, o5), o6);
float o789 = min(min(o7, o8), o9);
float o101112 = min(min(o10, o11), o12);
return min(min(min(o123, o456), o789), o101112);
}
float sdBikkuri(vec3 p, float size) {
float s = size * 2.0;
vec3 p4b = p;
float b1 = sdBox(p4b, vec3(size));
float b2 = sdBox(p4b + vec3(0.0, s * 2.0, 0.0), vec3(size));
float b3 = sdBox(p4b + vec3(0.0, -s, 0.0), vec3(size));
float b4 = sdBox(p4b + vec3(0.0, -s * 2.0, 0.0), vec3(size));
return min(min(min(b1, b2), b3), b4);
}
float sdLetter(vec3 p) {
p.y -= 20.0;
float scl = 3.0/acos(-1.0);
vec2 pos2d = p.xz;
float r = length(pos2d);
pos2d = vec2(log(r), atan(pos2d.y, pos2d.x));
pos2d.x += time / 2.0;
pos2d.y += time / 8.0;
pos2d *= scl;
pos2d = mod(pos2d, 1.0) - 0.5;
float mul = r/scl;
p = vec3(pos2d.y, p.y / mul, pos2d.x);
float size = 0.01;
float s = size * 2.0;
vec3 p4y = p + vec3(s*15.0 + size*3.0, 0.0, 0.0);
float y1 = sdBox(p4y, vec3(size));
float y2 = sdBox(p4y + vec3(s,-s,0.0), vec3(size));
float y3 = sdBox(p4y + vec3(-s,-s,0.0), vec3(size));
float y4 = sdBox(p4y + vec3(0.0,s,0.0), vec3(size));
float y5 = sdBox(p4y + vec3(0.0,s * 2.0,0.0), vec3(size));
float y6 = sdBox(p4y + vec3(s * 2.0,-s * 2.0,0.0), vec3(size));
float y7 = sdBox(p4y + vec3(-s * 2.0,-s * 2.0,0.0), vec3(size));
float y = min(min(min(min(min(min(y1, y2), y3), y4), y5), y6), y7);
float b = min(
sdBikkuri(p + vec3(-s*15.0 + size*-3.0, 0.0, 0.0), size),
sdBikkuri(p + vec3(-s*10.0 + size*-2.0, 0.0, 0.0), size)
);
float o1 = sdO(p + vec3(s*10.0 + size*2.0, 0.0, 0.0), size);
float o2 = sdO(p + vec3(s*5.0 + size, 0.0, 0.0), size);
float o3 = sdO(p + vec3(0.0, 0.0, 0.0), size);
float o4 = sdO(p + vec3(-s*5.0 - size, 0.0, 0.0), size);
float o = min(min(min(o1, o2), o3), o4);
float letter = min(min(y, o), b);
return letter * mul;
}
MarchResult crabMap(vec3 p, float dist) {
MarchResult result;
result.dist = dist;
vec3 p4body = p;
p4body.y -= abs(sin(time * 5.0 + 0.1)) * 0.3;
p4body.x += sin(time * 5.0 - 0.1) * 0.3;
float body = sdCapsule(p4body, vec3(0.25, 0.0, 0.0), vec3(-0.25, 0.0, 0.0), 0.5);
float eye = sdEye(p4body);
float foot = sdFoot(p);
float arm = sdArm(p4body);
body = smoothUnion(body, eye, 0.3);
body = smoothUnion(body, foot, 0.1);
body = smoothUnion(body, arm, 0.1);
float eyeBall = min(sdSphere(p4body + vec3(0.19, -1.0, -0.15*0.4), 0.15 * 0.6), sdSphere(p4body + vec3(-0.19, -1.0, -0.15*0.4), 0.15 * 0.6));
float eyeBallBlack = min(sdSphere(p4body + vec3(0.19, -1.0, -0.325*0.4), 0.05 * 0.6), sdSphere(p4body + vec3(-0.19, -1.0, -0.325*0.4), 0.05 * 0.6));
float mouth = sdMouth(p4body, 1.0 + abs(sin(p.z*2.0 + time)));
float d = body;
if(d < result.dist) {
result.dist = d;
result.material = MAT_BODY;
}
d = mouth;
if(d < result.dist) {
result.dist = d;
result.material = MAT_MOUTH;
}
d = eyeBall;
if(d < result.dist) {
result.dist = d;
result.material = MAT_EYE_BALL;
}
d = eyeBallBlack;
if(d < result.dist) {
result.dist = d;
result.material = MAT_MOUTH;
}
return result;
}
MarchResult map(vec3 p) {
vec3 p2 = p;
MarchResult result;
result.dist = 1E9;
p.z -= time * 4.0;
if(floor(mod(time/2.0, 8.0)) == 7.0) {
p.y += sin(floor(p.z/4.0) + floor(p.x/8.0)*2.0 + time * 15.0) * 2.0;
} else {
p.y += sin(floor(p.z/4.0) + floor(p.x/8.0)*2.0 + time * 8.0)*0.5;
}
p.z = mod(p.z, 4.0) - 2.0;
p.x = mod(p.x, 8.0) - 4.0;
result = crabMap(p, result.dist);
vec3 p4daiza = p;
p4daiza += vec3(0.0, 100.65, 0.0);
p4daiza.yz *= rot(acos(-1.0)/2.0);
float d = sdHexPrism(p4daiza, vec2(1.2, 100.1));
if(d < result.dist) {
result.dist = d;
result.material = MAT_DAIZA;
}
d = sdLetter(p2);
if(d < result.dist) {
result.dist = d;
result.material = MAT_GAMING;
}
if(floor(mod(time/2.0, 8.0)) == 7.0) result.material = MAT_GAMING;
return result;
}
vec3 getNormal(vec3 p) {
float d = 0.1;
return normalize(vec3(
map(p + vec3(d, 0.0, 0.0)).dist - map(p + vec3(-d, 0.0, 0.0)).dist,
map(p + vec3(0.0, d, 0.0)).dist - map(p + vec3(0.0, -d, 0.0)).dist,
map(p + vec3(0.0, 0.0, d)).dist - map(p + vec3(0.0, 0.0, -d)).dist
));
}
vec3 diffuse(vec3 n, vec3 l, vec3 col) {
float diff = clamp(dot(l, n), 0.0, 1.0);
return vec3(diff) * col;
}
vec3 specular(vec3 n, vec3 l, vec3 v) {
float NdotL = dot(n, l);
vec3 r = normalize(2.0 * n * NdotL - l);
float spec = pow(max(0.0, dot(r, v)), 100.0);
return vec3(spec);
}
void main() {
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
float c = sin(p.x * 5.0 + time);
c += sin((p.y * 10.0 + time)/2.0);
c += sin((p.x * 2.0 + p.y * 20.0 + time)/2.0);
c = sin(c * 5.0 + time * 2.0);
c += cos(p.x*10.0)*sin(p.x*10.0 + time);
c = cos(c * 3.0 + time * 2.0 + p.y * 20.0);
vec3 cPos = vec3(sin(time / 2.0) * 8.0, 2.5, 0.0);
vec3 ta = vec3(0.0, 0.0, -10.0);
vec3 cDir = normalize(ta - cPos);
vec3 cSide = cross(cDir, vec3(0.0, 1.0, 0.0));
vec3 cUp = cross(cSide, cDir);
float targetDepth = 1.0;
vec3 ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth);
float distance = 0.0;
float rLen = 0.0;
vec3 rPos = cPos;
vec3 lightDir = -cDir;
vec3 color = vec3(0.0);
float alpha = 0.0;
MarchResult marchResult;
for(int i = 0; i < 70; i++) {
marchResult = map(rPos);
distance = marchResult.dist;
rLen += distance;
if(abs(marchResult.dist) < 0.001) {
vec3 normal = getNormal(rPos);
alpha = 1.0;
if(marchResult.material == MAT_BODY) {
vec3 diff = diffuse(normal, lightDir, vec3(1.0, 0.0, 0.0));
vec3 spec = specular(normal, lightDir, -cDir);
color = (diff + spec);
} else if(marchResult.material == MAT_MOUTH) {
color = diffuse(normal, lightDir, vec3(0.2, 0.2, 0.2));
} else if(marchResult.material == MAT_GAMING) {
color = diffuse(normal, lightDir, hsv2rgb(time, 1.0 ,1.0));
} else if(marchResult.material == MAT_DAIZA) {
color = diffuse(normal, lightDir, vec3(0.2, 0.1, 0.0));
} else {
color = diffuse(normal, lightDir, vec3(1.0));
}
break;
}
rPos = cPos + ray * rLen;
}
alpha = exp(rLen * -0.095);
vec3 noise = mix(vec3(0.6, 0.1, 0.95), vec3(0.8, 0.9, 0.0), c) * 0.85;
color = mix(color, noise, step(alpha, 0.001));
gl_FragColor = vec4(color, 1.0);
}