Chapter 4: 添加一个小球
前言
本节中将在屏幕上画出一个小球。
利用球体的表达式与光线表达式,建立方程组,继而求解出光线与小球表面的交点位置。
正文
借助向量运算,小球表面的公式可以表示为如下形式:
其中,c 表示小球圆心, R表示小球半径。
代入光线公式:
得
将该式展开得
向量A,B,C都是已知量,该等式相当于求解 一元二次方程, 当方程有两个解时,可认为光线穿过小球。
修改main 中的函数
bool hit_sphere(const vec3& center, float radius, const ray& r) {
vec3 oc = r.getOrigin() - center;
float a = dot(r.getDirection(), r.getDirection());
float b = 2 * dot(oc, r.getDirection());
float c = dot(oc, oc) - radius * radius;
return (b * b - 4 * a * c > 0);
}
// -------- color 函数用于返回背景的颜色 -------- //
vec3 color(const ray& r) {
// 如果光线穿过小球,将其设为红色.小球位于(0,0,-1),半径为0.5
if (hit_sphere(vec3(0,0,-1), 0.5, r)) {
return vec3(1, 0, 0);
}
vec3 unit_direction = unit_vector(r.getDirection());
// 标准化之后的y值值域为[-1, 1], 将其映射到[0, 1]
float t = 0.5 * (unit_direction.y() + 1.0);
// 将设向不同方向的光赋予不同的颜色
return (1.0 - t) * vec3(1.0, 1.0, 1.0) + t * vec3(0.5, 0.7, 1.0);
}
实验结果:
将得到一个这样的小球,虽然当前锯齿还有点明显。