베지어(bezier)와 기울기

베지어 함수의 코드는 다음과 같다.

vec3 bezier(vec3 P0, vec3 P1, vec3 P2, vec3 P3, float t) {
  float u = 1.0 - t;
  float tt = t * t;
  float uu = u * u;
  float uuu = uu * u;
  float ttt = tt * t;

  vec3 p = uuu * P0; // (1-t)^3 * P0
  p += 3.0 * uu * t * P1; // 3*(1-t)^2*t*P1
  p += 3.0 * u * tt * P2; // 3*(1-t)*t^2*P2
  p += ttt * P3; // t^3*P3

  return p;
}

베지어 상의 접선에 대한 함수 코드는 다음과 같다.

vec3 bezierGrad(vec3 P0, vec3 P1, vec3 P2, vec3 P3, float t) {
  return 3.0 * (1.0 - t) * (1.0 - t) * (P1 - P0) +
    6.0 * (1.0 - t) * t * (P2 - P1) +
    3.0 * t * t * (P3 - P2);
}

접선에 대한 벡터를 90도 회전하면 베지어의 법선 벡터를 구할 수 있다.

Ray-Sphere 계산

수식

코드

uniform vec3 uResolution;
uniform float uTime;
uniform vec4 uMouse;

// v = a -> 0
// v = b -> 1 
// v = (a+b)/2 -> 0.5
float remap01(float a, float b, float v) {
  return (v - a) / (b - a);
}

void main() {
  vec2 uv = (gl_FragCoord.xy - .5 * uResolution.xy) / uResolution.y;

  vec3 col = vec3(0);
  vec3 Ro = vec3(0);
  vec3 Rd = normalize(vec3(uv.x, uv.y, 1.));
  vec3 S = vec3(0, 0, 3);
  float R = 1.;

  float tp = dot(S - Ro, Rd);
  vec3 Ptp = Ro + Rd * tp;
  float y = length(S - Ptp);
  
  if(y < R) {
    float x = sqrt(R*R - y*y);
    float t1 = tp - x;
    float t2 = tp + x;

    float c = remap01(S.z, S.z - R, t1);
    col = vec3(c);
  }
  
  gl_FragColor = vec4(col, 1.0);
}

결과