虚拟机代码:
作业五的任务是写一个简单的光线追踪
整体流程说明
光线传输、光线与三角形求交。我们采用了这样的方法寻找光线与场景的交点:
1,遍历场景中的所有物体,判断光线是否与它相交。在场景中的物体数量不大时,该做法可以取得良好的结果,
2,但当物体数量增多、模型变得更加复杂,该做法将会变得非常低
效。
理论依据
Whitted-Style 光线追踪
步骤:
1,假设人眼就一个光源,所有的光线都是从人眼发出,人眼前是一个离散的二维平面,对于二维平面的每个像素点向外射出一条射线,打到三维物体上,此时会发生折射和反射
2,和光源直接连接每个折射点和散射点,观察光源是否能够到达这些点,通过深度就可以测得
3,然后每个光源可见的点,都是一条光路,此时分为首次光源和二次光源,将这些光路的能量汇总起来,就是一个像素点所得到的所有光的能量
求dir和三角形平面是否相交
依据的公式
O + tD = αA + βB + (1- α - β)C
依据上面的公式就可以推出 S S1 S2 E1 E2 的结果
castRay函数如何理解?
1,此函数用于计算交点处的颜色;
2,如果相交对象的材质为反射和折射,我们计算反射/折射方向,并向场景中投射两条新光线;
3,当表面是透明的,我们使用菲涅尔方程的结果混合反射和折射颜色,菲涅尔方程计算反射和折射量取决于曲面法线、入射视图方向表面折射率;
4,如果表面是漫反射我们使用Phong照明模型来计算颜色
计算从像素平面发射出去的观察方向
步骤
1,因左上角为(0,0),右下角为(scene.width, scene.height),先将像素坐标系归一化到(0,1) 则有 (float)i + 0.5)/scene.width)
2,将坐标系从的范围从[0,1] 变换到 [-1,1] ,则有(2*(((float)i + 0.5)/scene.width) - 1),此时左上角的x变为 -1
3,因为像素平面不一定为正方形,则像素的形状不一定为正方形,所以以height为基准,有(2*(((float)i + 0.5)/scene.width) - 1) * imageAspectRati
4,因观察方向基于eye point 的坐标系下,所以最后乘scale,调整基于像素平面的所观察到的范围, float x = (2*(((float)i + 0.5)/scene.width) - 1) * imageAspectRatio * scale;
公式推导
代码
void Renderer::Render(const Scene& scene)
void Renderer::Render(const Scene& scene)
{
std::vector<Vector3f> framebuffer(scene.width * scene.height);
float scale = std::tan(deg2rad(scene.fov * 0.5f));
float imageAspectRatio = scene