Games101-作业5-光线与三角形相交
分析
这次作业还是比较简单的,主要是光线投射,需要填的部分就是把相机发出的光线坐标变换到物体所在的世界坐标和利用上课讲过的公式计算射线与三角形的交点。
想搞清楚这个过程可以参考Ray-Tracing: Generating Camera Rays
CastRay
来源:https://zhuanlan.zhihu.com/p/438520487
castRay是真正利用光线弹射着色的函数。其作用就是计算从摄像机出发,穿过每个像素击中的物体表面那个点的颜色。如果没有击中物体,就按背景颜色处理。
整个场景设置了光线最多弹射5次,所以在函数一开始,会看一下是不是超过第五次弹射了。如果是直接返回。
场景中的物体被设置了三种不同的材质属性,第一种透明的(REFLECTION_AND_REFRACTION),第二种镜面的(REFLECTION),第三种粗糙的(DIFFUSE_AND_GLOSSY)。当光线打在透明物体和镜面物体上时,由于这两种物体没有颜色,我们看到的颜色都是光线穿过它或者被反射到其他物体上的颜色,所以需要再次调用castRay函数,看一下下一次的反射或者折射的光线能不能打到有颜色的物体上。当光线打在粗糙的物体上,我们需要在光线和物体的交点上(hitpoint),看一下能不能看到光源(从hitpoint发射一条连接光源的线,看一下和场景里面的物体有没有交点,如果没有或者有交点但是交点在光线身后,则可以看到光源,即被光线照射)。如果能看到光源,则用Phong模型计算光照颜色,反之则在阴影内,变成黑色。另外,**光线打在粗糙的物体上后,不再做弹射。**这就是为啥我们最终渲染出来的阴影是硬阴影。
castRay函数中的菲涅尔函数是为了计算光线照射到一个物体后的反射与折射的比例。
Render
让写的就是把raster space中的像素坐标转换到world space中的坐标。
// generate primary ray direction
float x = (2 * ((i + 0.5) / scene.width) - 1) * scale * imageAspectRatio;
float y = (1 - 2 * ((j + 0.5) / scene.height)) * scale;
rayTriangleIntersect
射线与三角形相交,利用课上讲的MT算法公式。
bool rayTriangleIntersect(const Vector3f& v0, const Vector3f& v1, const Vector3f& v2, const Vector3f& orig,
const Vector3f& dir, float& tnear, float& u, float& v)
{
// TODO: Implement this function that tests whether the triangle
// that's specified bt v0, v1 and v2 intersects with the ray (whose
// origin is *orig* and direction is *dir*)
// Also don't forget to update tnear, u and v.
Vector3f E1 = v1 - v0, E2 = v2 - v0, S = orig - v0;
Vector3f S1 = crossProduct(dir, E2), S2 = crossProduct(S, E1);
float S1E1 = dotProduct(S1, E1);
tnear = 1.0 / S1E1 * dotProduct(S2, E2);
u = 1.0 / S1E1 * dotProduct(S1, S);
v = 1.0 / S1E1 * dotProduct(S2, dir);
return tnear > 0 && u >= 0 && u <= 1 && v >= 0 && v <= 1 && 1 - u - v >= 0 && 1 - u - v <= 1;
}