homework5: Whitted-Style Ray Tracing

理论回顾

发射光线

对于要渲染的像素点(x,y),其颜色是根据所接收到的不同波长光混合之后决定的。根据光路可逆的原理,要计算该店的颜色值,可以从眼睛处(eye point)向世界空间里发射一条光线,探测光线碰撞到了哪些物体,并根据物体的颜色来对像素点着色。总结下,光线追踪的方法基于以下三点:

  • 光线沿直线传播
  • 光线之间互不干扰
  • 光路可逆

考虑到光的量子性,前两者并不完全正确,但对渲染质量影响比较小,故按照经典光学的理论模型处理。发射光线的时候需要考虑两个问题:1、屏幕空间的像素点变换到世界空间;2、建立光线的数学模型

像素点坐标变换

目的:通过线性变换将屏幕空间的像素点变换到世界空间。

光栅化渲染方法需要先进行MVP变换,即首先通过模型变换将模型(TriangleMesh)从物体空间(通常在模型文件中定义)变换到世界空间;通过相机变换将世界空间的物体变换到以摄像机的xyz方向轴为基底的线性空间,即相机空间;投影变换将相机空间的物体变化到标准视椎体(CVV),这一步往往会进行裁剪;最后通过视口变换将CVV里的物体变换到屏幕空间;

基于光线追踪的渲染方法只需要先进行MVP变换中的M即可,因为只需要把模型准确放在了世界空间内,然后就可以从摄像机向世界空间投射光线,如图所示:

在这里插入图片描述

首先要解决的是如何将屏幕空间的像素点映射到摄像机成像的“虚拟平面”上,同时需要考虑屏幕的宽高比和射线机的视角。

光线的数学模型

在这里插入图片描述

光线方程基于直线的向量式方程,需要注意的是从o点发出的光线是条射线,要保证t≥0。

三角形求交

大部分模型都是以三角形为片元构成的,因此研究三角形求交具有普遍适用性,另外由于三角形在空间内一定是个平面,所以光线和任意一个三角形最多有一个交点。

补充说明:对于空间中一个模型,如果要判断某一个点是在模型的内部还是外部,可以计算从这点发出的光线打到物体表面上的交点数量,如果交点个数是奇数,说明点在物体内;偶数个交点说明点在物体外。

在这里插入图片描述

着色

根据相交物体的材质生成颜色,并递归累加到像素点上。不同的材质会采用不同的着色方法:

  • 反射和透射材质

    fresnel equations+castRay()

  • 反射材质

    fresnel equations+castRay()

  • 漫反射材质

    Phong illumation model

代码展示

求光线的方向

先进行逆视口变换,将屏幕像素变换到[-1,1]。要注意需要对y取反,因为屏幕空间的y坐标轴是从上到下的。

x=(2*float (i)+1)/scene.width - 1;
y=-(2*float (j)+1)/scene.height+1;

然后是根据视角和屏幕比例进行缩放

x*=scale * imageAspectRatio;
y*=scale;

三角形求交

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;
    Vector3f E2=v2-v0;
    Vector3f S=orig-v0;
    Vector3f S1=crossProduct(dir,E2);
    Vector3f S2=crossProduct(S,E1);

    float scaler=dotProduct(S1,E1);

    float t=dotProduct(S2,E2)/scaler;
    float b1=dotProduct(S1,S)/scaler;
    float b2=dotProduct(S2,dir)/scaler;
    float b0=1-b1-b2;

    if(b1>=0&&b2>=0&&b1<=1&&b2<=1&&t>0){
        // uv是交点的重心坐标
        u = b1;
        v = b2;
        tnear=t;
        return true;
    }
    return false;
}

要注意判断t>0,不然会导致计算错误。当找到交点的时候返回true,并更新u, v, tnear。

在这里插入图片描述

参考:

https://zhuanlan.zhihu.com/p/431092843

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值