您的位置:首页 > 其它

【Ray Tracing in One Weekend】(ch4)场景中第一个物体,球体

2017-11-29 09:15 916 查看

Chapter 4: Adding a sphere

初高中学过球体的公式:

x∗x+y∗y+z∗z=R∗R

即点p(x,y,z),若满足上方程,即在球上。

对于中心在C(cx,cy,cz)的球体:

(x−cx)∗(x−cx)+(y−cy)∗(y−cy)+(z−cz)∗(z−cz)=R∗R

上式也可根据pC两点写作向量的形式:

dot((p−C),(p−C))=R∗R=(x−cx)∗(x−cx)+(y−cy)∗(y−cy)+(z−cz)∗(z−cz)

可以把点 p 换做 Ray 上一点 p(t)

dot((p(t)−C),(p(t)−C))=R∗R

也写作

dot((A+t∗B−C),(A+t∗B−C))=R∗R

可进一步写作

t∗t∗dot(B,B)+2∗t∗dot(A−C,A−C)+dot(C,C)−R∗R=0

分析此等式,发现其就是我们学过的一元二次方程,根据求根公式就可判断方程有无根,即射线有没有与球体相交。



修改 Main.cpp 中部分代码如下:

bool hit_sphere(const Vec3& center, float radius, const Ray& r)
{
Vec3 oc = r.origin() - center;
float a = dot(r.direction(), r.direction());
float b = 2.0f*dot(oc, r.direction());
float c = dot(oc, oc) - radius*radius;
float discrimiant = b*b - 4.0f*a*c;
return (discrimiant > 0.0f);
}

Vec3 Color(const Ray& r)
{
if (hit_sphere(Vec3(0.0f, 0.0f, -1.0f), 0.5f, r))
return Vec3(1.0f, 0.0f, 0.0f);

Vec3 unit_direction = unit_vector(r.direction());
float t = 0.5f*(unit_direction.y() + 1.0f);

//(1-t)*白色+t*蓝色,结果是一个蓝白的渐变
return (1.0f - t)*Vec3(1.0f, 1.0f, 1.0f) + t*Vec3(0.5f, 0.7f, 1.0f);
}


运行,结果如下:



(吐槽:怎么有点像霓虹国国旗呢)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: