第 13 课:SDF Cat - Whiskers
实现
uniform vec2 iResolution;
uniform float iTime;
const vec3 shapeColor = vec3(1.0, 0.3, 0.3);
const vec3 backgroundColor = vec3(0.12);
float sdfCircle(vec2 center, float r, vec2 pos) {
return distance(center, pos) - r;
}
float sdfBox(vec2 center, vec2 size, vec2 pos) {
vec2 d = abs(pos - center) - size;
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
}
float softMax(float a, float b, float k) {
return log(exp(k * a) + exp(k * b)) / k;
}
float softMin(float a, float b, float k) {
return -softMax(-a, -b, k);
}
mat2 rotation(float theta){
return transpose(mat2(
vec2(cos(theta),-sin(theta)),
vec2(sin(theta),cos(theta))
));
}
float makeEar(vec2 center, vec2 uv){
float earH = 60.0;
float earA = sdfCircle(center + vec2(-35.0,earH), 60.0, uv);
float earB = sdfCircle(center + vec2(35.0,earH), 60.0, uv);
float earA_inn = sdfCircle(center + vec2(-35.0,earH-5.0), 60.0, uv);
float earB_inn = sdfCircle(center + vec2(35.0,earH-5.0), 60.0, uv);
float earOuter = max(earA, earB);
float earInner = max(earA_inn, earB_inn);
return max(earOuter, -earInner);
}
float makeWhiskers(vec2 center, vec2 uv){
float whiskerLength = 35.0;
float timeOffset = -3.14;
vec2 uv_whiskerRotation_leftUp = rotation(-0.314-sin(iTime + timeOffset)*0.1)*uv;
vec2 uv_whiskerRotation_leftLow = rotation(-0.628-sin(iTime + timeOffset)*0.1)*uv;
float whiskerLeftUpper = sdfBox(center + vec2(-60.0,-10.0), vec2(whiskerLength, 1.0), uv_whiskerRotation_leftUp);
float whiskerLeftLower = sdfBox(center + vec2(-60.0,-10.0), vec2(whiskerLength, 1.0), uv_whiskerRotation_leftLow);
vec2 uv_whiskerRotation_rightUp = rotation(0.314+sin(iTime + timeOffset)*0.1)*uv;
vec2 uv_whiskerRotation_rightLow = rotation(0.628+sin(iTime + timeOffset)*0.1)*uv;
float whiskerRightUpper = sdfBox(center + vec2(60.0,-10.0), vec2(whiskerLength, 1.0), uv_whiskerRotation_rightUp);
float whiskerRightLower = sdfBox(center + vec2(60.0,-10.0), vec2(whiskerLength, 1.0), uv_whiskerRotation_rightLow);
return min(min(whiskerLeftUpper,whiskerLeftLower),min(whiskerRightUpper,whiskerRightLower));
}
void main() {
vec2 uv = gl_FragCoord.xy;
// make 0 the center
uv.x -= iResolution.x * 0.5;
uv.y -= iResolution.y * 0.5;
vec2 center = vec2(0.5);
float head = sdfCircle(center, 60.0 + sin(iTime), uv);
float timeOffset = -3.14;
vec2 rightEarRotation = rotation(0.628+sin(iTime + timeOffset)*0.1)*uv;
vec2 leftEarRotation = rotation(-0.628+sin(iTime + timeOffset)*-0.1)*uv;
float earRight = makeEar(center, rightEarRotation);
float earLeft = makeEar(center, leftEarRotation);
float ear = min(earRight,earLeft);
float u = softMin(ear, head, 0.25) * makeWhiskers(center, uv); // cat;
float t = clamp(u, 0.0, 1.0);
gl_FragColor = vec4(mix(shapeColor, backgroundColor, t), 1.0);
}