跳到主要内容
← Signed Distance Field

Signed Distance Field

SDF Cat - Whiskers

shader-learning 自学第 13 课:SDF Cat - Whiskers

实时渲染 · 2D 片段 GLSL

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