网站营销型企业销售平台,如何在网站上做咨询浮动窗口,wordpress去除版权,wordpress空间安装教程视频题目
光线追踪的核心算法: 1.光线的生成 2.光线与三角的相交
题解
1.光线的生成 如课件中的图所示#xff1a; image plane 就是 代码中的scene的FrameBuffer。 但是#xff0c;FrameBuffer 是窗口坐标系中#xff0c;而光线是世界坐标系中的。所以我们需要将scene中的屏…题目
光线追踪的核心算法: 1.光线的生成 2.光线与三角的相交
题解
1.光线的生成 如课件中的图所示 image plane 就是 代码中的scene的FrameBuffer。 但是FrameBuffer 是窗口坐标系中而光线是世界坐标系中的。所以我们需要将scene中的屏幕坐标 p o s s c r e e n pos_{screen} posscreen转换为世界坐标 p o s w o r l d pos_{world} posworld, 这个就可以按照作业3 坐标转换回顾 中局部坐标到窗口坐标的变换进行逆变换就可以了。 为了简化操作观察点在原点image plane 在 ( 0 , 0 , − 1 ) (0,0,-1) (0,0,−1)位置如此世界变换矩阵、观察矩阵都是单位矩阵。接下来只需要做投影变换、透视除法和视口变换的逆变换即可。由于z值已知所以在推算的过程中可以不考虑z值。通过手动推算可以得到以下公式 x w o r l d a s p e c t ∗ t a n ( f o v 2 ) ∗ ( 1 − 2 w ∗ x s c r e e n ) y w o r l d t a n ( f o v 2 ) ∗ ( 1 − 2 w ∗ y s c r e e n ) x_{world}aspect * tan(\frac{fov}{2})* (1 - \frac{2}{w} * x_{screen} ) \\ y_{world}tan(\frac{fov}{2})* ( 1 - \frac{2}{w} * y_{screen} ) xworldaspect∗tan(2fov)∗(1−w2∗xscreen)yworldtan(2fov)∗(1−w2∗yscreen) x w o r l d x_{world} xworld 为世界坐标 x s c r e e n x_{screen} xscreen 为屏幕坐标注意最后需要根据左右手和 窗口坐标系和屏幕坐标系的y轴反向加上相应的正负号。 最终image plane 中的 每个像素的世界坐标减去观察点eye_pos(0,0,0) 然后归一化即可得到光线的方向。
具体的代码如下 std::vectorVector3f framebuffer(scene.width * scene.height);float scale std::tan(deg2rad(scene.fov * 0.5f));float imageAspectRatio scene.width / (float)scene.height;// Use this variable as the eye position to start your rays.Vector3f eye_pos(0);int m 0;for (int j 0; j scene.height; j){for (int i 0; i scene.width; i){// generate primary ray directionfloat x0;float y0;// TODO: Find the x and y positions of the current pixel to get the direction// vector that passes through it.// Also, dont forget to multiply both of them with the variable *scale*, and// x (horizontal) variable with the *imageAspectRatio* // 将屏幕坐标转换为NDC坐标// 然后将NDC坐标转换为世界坐标x (2 * (i 0.5) / (float)scene.width - 1) * scale * imageAspectRatio;y (1 - 2 * (j 0.5) / (float)scene.height) * scale;Vector3f dir Vector3f(x, y, -1); // Dont forget to normalize this direction!dir normalize(dir);framebuffer[m] castRay(eye_pos, dir, scene, 0);}UpdateProgress(j / (float)scene.height);}光线和三角形相交 课程中介绍了两种方式第一种比较好理解就是先判断射线是否和平面相交如果相交在判断交点是否在三角形内部。 如ppt 中所示
第二种方式Moller Trubmber 算法这种方式可以一次计算出 t以及交点在重心坐标系中的坐标值。Moller Trubmber 算法的推导可以参考文档
根据公式实现的代码如下
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// thats specified bt v0, v1 and v2 intersects with the ray (whose// origin is *orig* and direction is *dir*)// Also dont forget to update tnear, u and v.// reference: moller trubmbore algorithmVector3f v0v1 v1 - v0;Vector3f v0v2 v2 - v0;Vector3f pvec crossProduct(dir, v0v2);float det dotProduct(v0v1, pvec);if (fabs(det) 1e-8) return false;float invDet 1 / det;Vector3f tvec orig - v0;u dotProduct(tvec, pvec) * invDet;if (u 0 || u 1) return false;Vector3f qvec crossProduct(tvec, v0v1);v dotProduct(dir, qvec) * invDet;if (v 0 || u v 1) return false;tnear dotProduct(v0v2, qvec) * invDet;return tnear 0;
}结果 作业答案
本次作业的答案放在的git仓库中作业地址