# 光线步进

  • 3D Signed Distance Function
  • Ray Marching

# 朴素的球

#define TMIN 0.1
#define TMAX 20.0
#define RAYMARCH_TIME 128
#define PRECISION .001

vec2 fixUV(in vec2 c) {
  return (2. * c - iResolution.xy) / min(iResolution.x, iResolution.y);
}

float sdfSphere(in vec3 p){
  return length(p) - .5;
}

float rayMarch(in vec3 ro, in vec3 rd){
  float t = TMIN;
  for(int i = 0; i < RAYMARCH_TIME && t < TMAX; i++){
    vec3 p = ro + t * rd; //步进
    float d = sdfSphere(p);
    if(d < PRECISION){
      break;
    }
    t += d;
  }
  return t;
}

vec3 render( in vec2 uv){
  vec3 color = vec3(0.);
  vec3 ro = vec3(0., 0., -2.); // 相机位置
  vec3 rd = normalize(vec3(uv, 0.) - ro); // 对每个像素的方向向量
  float t = rayMarch(ro,rd); // 对每个像素进行步进
  if(t < TMAX){
    color = vec3(1.);
  }
  return color;
}

void mainImage (out vec4 fragColor, in vec2 fragCoord){
    vec2 uv = fixUV(fragCoord);    
    vec3 color = render(uv);
    fragColor = vec4(color, 1.); // rgba
}

# 点光源

#define TMIN 0.1
#define TMAX 20.0
#define RAYMARCH_TIME 128
#define PRECISION .001

vec2 fixUV(in vec2 c) {
  return (2. * c - iResolution.xy) / min(iResolution.x, iResolution.y);
}

// 球体的符号距离函数
float sdfSphere(in vec3 p) { 
  return length(p - vec3(0., 0., 2.)) - 1.5; 
}

// 光线步进
float rayMarch(in vec3 ro, in vec3 rd) {
  float t = TMIN;
  for (int i = 0; i < RAYMARCH_TIME && t < TMAX; i++) {
    vec3 p = ro + t * rd; // 步进
    float d = sdfSphere(p);
    if (d < PRECISION) {
      break;
    }
    t += d;
  }
  return t;
}

vec3 calcNormal(in vec3 p) {
  const float h = 0.0001;
  const vec2 k = vec2(1, -1);
  return normalize(
      k.xyy * sdfSphere(p + k.xyy * h) + k.yyx * sdfSphere(p + k.yyx * h) +
      k.yxy * sdfSphere(p + k.yxy * h) + k.xxx * sdfSphere(p + k.xxx * h)

  );
}

vec3 render(in vec2 uv) {
  vec3 color = vec3(0.);
  vec3 ro = vec3(0., 0., -2.); // 相机位置
  vec3 rd = normalize(vec3(uv, 0.) - ro);
  float t = rayMarch(ro, rd);
  if (t < TMAX) {
    // color = vec3(1.);
    vec3 p = ro + t * rd; // 当前位置
    vec3 n = calcNormal(p); // 法向量
    vec3 light = vec3(1., 2., 0.); // 光源
    float dif = clamp(dot(normalize(light - p),n),0., 1.);
    color = dif * vec3(1.);
  }
  return color;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  vec2 uv = fixUV(fragCoord);
  vec3 color = render(uv);
  fragColor = vec4(color, 1.); // rgba
}

# 环境光

#define TMIN 0.1
#define TMAX 20.0
#define RAYMARCH_TIME 128
#define PRECISION .001

vec2 fixUV(in vec2 c) {
  return (2. * c - iResolution.xy) / min(iResolution.x, iResolution.y);
}

// 球体的符号距离函数
float sdfSphere(in vec3 p) { return length(p - vec3(0., 0., 2.)) - 1.5; }

// 光线步进
float rayMarch(in vec3 ro, in vec3 rd) {
  float t = TMIN;
  for (int i = 0; i < RAYMARCH_TIME && t < TMAX; i++) {
    vec3 p = ro + t * rd; // 步进
    float d = sdfSphere(p);
    if (d < PRECISION) {
      break;
    }
    t += d;
  }
  return t;
}

// 计算法向量
vec3 calcNormal(in vec3 p) {
  const float h = 0.0001;
  const vec2 k = vec2(1, -1);
  return normalize(
      k.xyy * sdfSphere(p + k.xyy * h) + k.yyx * sdfSphere(p + k.yyx * h) +
      k.yxy * sdfSphere(p + k.yxy * h) + k.xxx * sdfSphere(p + k.xxx * h));
}

vec3 render(in vec2 uv) {
  vec3 color = vec3(0.);
  vec3 ro = vec3(0., 0., -2.); // 相机位置
  vec3 rd = normalize(vec3(uv, 0.) - ro);
  vec3 light = vec3(1., 2., 0.); // 光源
  float t = rayMarch(ro, rd);
  if (t < TMAX) {
    vec3 p = ro + t * rd;          // 当前位置
    vec3 n = calcNormal(p);        // 法向量
    float dif = clamp(dot(normalize(light - p), n), 0., 1.);
    float amb = .5 + .5 * dot(n, vec3(0., 1., 0.));     // 环境光
    color = amb * vec3(.25, .25, .25) + dif * vec3(1.); // 叠加
  }
  return color;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
  vec2 uv = fixUV(fragCoord);
  vec3 color = render(uv);
  fragColor = vec4(color, 1.); // rgba
}