光线追踪

$$\quad\\$$
从相机向平面上某点引一条射线$\vec{v}$

定义物体的符号距离函数$f$

当$\vec{v}$行进至符号距离函数$f$为负数的点$p$时停止

通过微小变化算出此处$f$的梯度$\nabla f$

计算$\vec{pL}$与$\nabla f$的余弦,作为该点的亮度
$$\quad$$
定义最大步进次数、距离与精度,

const int steps_max = 255;
const float d_min = 0.0;
const float d_max = 100.0;
const float precision = 0.001;

定义旋转矩阵

mat3 rotateXYZ(float ax,float ay,float az){
    float cx=cos(ax);
    float sx=sin(ax);
    float cy=cos(ay);
    float sy=sin(ay);
    float cz=cos(az);
    float sz=sin(az);
    return mat3(
        vec3(cy*cz,-cy*sz,sy),
        vec3(cz*sx*sy+cx*sz,cx*cz-sx*sy*sz,-cy*sx),
        vec3(-cx*cz*sy+sx*sz,cz*sx+cx*sy*sz,cx*cy)
    );
}

mat3 rotate(){
    return rotateXYZ(-iTime,-iTime,-iTime);}

定义十二面体的符号距离函数

float sdf(vec3 p,mat3 transform)
{
  vec3 offset = vec3(0.,0., 0.5);
  p=p*transform-offset;
  float d1=(length(p)-abs(length(p)*0.6*1.71353
  /(p.x*0.+p.y*0.+p.z*1.53884)));
  float d2=(length(p)-abs(length(p)*0.6*1.71353
  /(p.x*1.37638+p.y*0.+p.z*0.688191)));
  float d3=(length(p)-abs(length(p)*0.6*1.71353
  /(p.x*0.425325+p.y*-1.30902+p.z*0.688191)));
  float d4=(length(p)-abs(length(p)*0.6*1.71353
  /(p.x*1.11352+p.y*0.809017+p.z*-0.688191)));
  float d5=(length(p)-abs(length(p)*0.6*1.71353
  /(p.x*-1.11352+p.y*0.809017+p.z*0.688191)));
  float d6=(length(p)-abs(length(p)*0.6*1.71353
  /(p.x*0.425325+p.y*1.30902+p.z*0.688191)));
  return max(d1,max(d2,max(d3,max(d4,max(d5,d6)))));
}

定义rayMarch函数获取光线碰到物体的位置

float rayMarch(vec3 camera, vec3 reverse_direction,
               float d_min, float d_max) {

  float depth = d_min;

  for (int i = 0; i < steps_max; i++) {
    vec3 p = camera + depth * reverse_direction;
    float d = sdf(p,rotate());
    depth += d;
    if (d < precision || depth > d_max) break;
  }

  return depth;
}

获取物体表面外法线方向

vec3 calcNormal(vec3 p) {
    vec2 e = vec2(1.0, -1.0) * 0.0005;
    return normalize(
      e.xyy * sdf(p + e.xyy,rotate()) +
      e.yyx * sdf(p + e.yyx,rotate()) +
      e.yxy * sdf(p + e.yxy,rotate()) +
      e.xxx * sdf(p + e.xxx,rotate()));
}

着色

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
  vec2 uv = (fragCoord-.5*iResolution.xy)/iResolution.y;

  vec3 col = vec3(0);
  vec3 camera = vec3(0, 0, 3);
  vec3 reverse_direction = normalize(vec3(uv, -1));

  float d = rayMarch(camera, reverse_direction,
                     d_min, d_max); 

  if (d > d_max) {
    col = vec3(0.6); 
  } else {
    vec3 p = camera + reverse_direction * d;
    vec3 normal = calcNormal(p);
    vec3 lightPosition = vec3(2, 2, 4);
    vec3 lightDirection = normalize(lightPosition - p);

    float dif = clamp(dot(normal, lightDirection), 0., 1.);

    col = vec3(dif);
  }

  fragColor = vec4(col, 1.0);
}

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器