学而思网校官网,北京网站优化推广收集,甘肃省建设厅网站官网,检测网站的seo效果1.实现Renderer.cpp 中的 Render()#xff1a;为每个像素生成光线
这里你需要为每个像素生成一条对应的光 线#xff0c;然后调用函数 castRay() 来得到颜色#xff0c;最后将颜色存储在帧缓冲区的相 应像素中。
我们要做的就是将屏幕空间下的坐标最后转换到世界空间的坐标…1.实现Renderer.cpp 中的 Render()为每个像素生成光线
这里你需要为每个像素生成一条对应的光 线然后调用函数 castRay() 来得到颜色最后将颜色存储在帧缓冲区的相 应像素中。
我们要做的就是将屏幕空间下的坐标最后转换到世界空间的坐标
这里一开始是处于屏幕空间坐标下的如下图这里假设原点在左上角opengl原点在左下角dx原点在左上角那么首先想到的是将ij分别加0.5取得像素中心坐标 接着将坐标变换到NDC空间NDC空间是一个长宽高取值范围为[-1,1]的立方体超过这个范围的顶点会被GPU剪裁。注在DirectX里面NDC的z方向取值范围是[0,1]
DX下的NDC空间如下图要转换到NDC空间下首先要用xy分别除以屏幕的宽度贺高度。然后NDC空间需要将坐标轴原点变回到屏幕中间位置。 i方向即宽方向[0,1]-[-1,1]因为变化是线性的很容易得到 i 2*i-1。 j方向即高方向[0,1]-[1,-1]因为变化是线性的很容易得到 i -2*i1 最后要将坐标转换到世界空间要解决两个问题
①横纵方向的长度并不是1:1的
②物体本身并不是在[-1,1]的[-1,1]是缩放后的范围。
解决办法
①imageAspectRatio即宽高比是原本scene的宽高比所以要想恢复原始的比例需要用 宽 * 宽高比即 x * imageAspectRatio。
②scale为一半可看角度fov/2的tan值即下图tan(α/2)它代表了原本图像屏幕高度与图像到X-Y平面距离的比值又由代码已给出的 Vector3f dir Vector3f(x, y, -1) 可以知道原本的图像屏幕距离X-Y平面为1所以scale即为原本的图像高度而现在的图像高度为1所以令x,y同时乘以scale即可得到原始世界坐标下的坐标。 综上所述最后直接给出代码计算
void Renderer::Render(const Scene scene)
{std::vectorVector3f framebuffer(scene.width * scene.height);//float scale std::tan(deg2rad(scene.fov * 0.5f));//宽高比float imageAspectRatio (float)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 x (2 * (((float)i 0.5) / scene.width) - 1)* imageAspectRatio * scale;float y (1.0 - 2 * ((float)j 0.5) / scene.height) * scale;// 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* //vector op,说明scene在z-1故znear距离人眼距离1 Vector3f dir normalize(Vector3f(x, y, -1)); // Dont forget to normalize this direction!framebuffer[m] castRay(eye_pos, dir, scene, 0);}UpdateProgress(j / (float)scene.height);}// save framebuffer to fileFILE* fp fopen(binary.ppm, wb);(void)fprintf(fp, P6\n%d %d\n255\n, scene.width, scene.height);for (auto i 0; i scene.height * scene.width; i) {static unsigned char color[3];color[0] (char)(255 * clamp(0, 1, framebuffer[i].x));color[1] (char)(255 * clamp(0, 1, framebuffer[i].y));color[2] (char)(255 * clamp(0, 1, framebuffer[i].z));fwrite(color, 1, 3, fp);}fclose(fp);
}
到这一步输出的结果
window下查看ppm图片貌似需要用到第三方软件这里给出我用的一个网站
在线查看 PPM 文件的免费在线工具 - ImageToStl 2.Triangle.hpp 中的 rayTriangleIntersect()实现视射线与三角形相交
主要就是根据这个公式分别带入不同的参数就可以 origin是相机的位置dir是射出的方向
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.Vector3f E1 v1 - v0, E2 v2 - v0 ;Vector3f S orig - v0,S1 crossProduct(dir, E2), S2 crossProduct(S, E1);if (dotProduct(S1, E1) 0) return false;tnear dotProduct(S2, E2) / dotProduct(S1, E1);u dotProduct(S1, S) / dotProduct(S1, E1);v dotProduct(S2, dir) / dotProduct(S1, E1);if (tnear 0 u 0 v 0 (1 - u - v) 0) return true;return false;
}
最后的结果