要考虑两个问题,首先是要求使这些法线单位化,方便着色。第二个就是要考虑到光线击中球的具体的位置的值,而不仅仅是考虑我们是否命中。
在原有基础上,修改Hit_Sphere()函数:
float Hit_Sphere(const point3& center, float radius, const ray& r)
{
auto lightSourceToSphereCenter = r.origin() - center;
auto a = dot(r.direction(), r.direction());
auto b = 2 * dot(r.direction(), lightSourceToSphereCenter);
auto c = dot(lightSourceToSphereCenter,lightSourceToSphereCenter) - radius * radius;
auto rootFunction = b * b - 4 * a * c;
if (rootFunction < 0) return -1;
else
return(-b - sqrt(rootFunction)) / (2.f * a);//求出具体的值
}
修改ray_color()函数
color ray_color(const ray& r)
{
auto t = Hit_Sphere(point3(0, 0, -1), 0.5, r);
if (t > 0.f)
{
auto N = unit_vector(r.at(t) - vec3(0, 0, -1));
return 0.5f * color(N.x() + 1, N.y() + 1, N.z() + 1);//将[-1,1]范围内的值映射到[0,1]范围内。
//在这里,通过将向量N的每个分量都加1,将其映射到了[0,2]范围内,然后再将其除以2,就得到了[0,1]范围内的值,
//这样就可以作为颜色分量的取值了
}
vec3 unit_direction = unit_vector(r.direction());
t = 0.5f * (unit_direction.y() + 1.0f);
//(1−t)×c1 + t×c2 线性插值
return (1.f - t) * color(1.f, 1.f, 1.f) + t * color(0.5f, 0.7f, 1.f);
}
可以得到如下图: