0%

【Games 101】HomeWork 5:光线与三角形相交

HomeWork 5:光线与三角形相交

这一个作业主要是光线追踪,我们要实现的是:

  • 从每个像素打出一条光线;
  • 判断光线和三角形是否相交

有的东西课上没有讲,具体的话可以看一下注释!

同步的知识点在这一片文章:

【Games 101】Lec 13:光线追踪 1(Shadow Mapping,Whitted-Style Ray Tracing)

Renderer.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
主渲染函数。
在这里,我们迭代图像中的所有像素,从每个像素打出一条光线到场景中;
framebuffer 的内容被保存到一个文件中。

我的妈,这个是真的有点难哇... 主要是课上也没讲...
具体可以看这两篇文章:
https://zhuanlan.zhihu.com/p/475136497
https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays.html

特别是第二篇,分析的特别清楚!
看完就知道要干嘛了(就是需要变换一下坐标)
*/
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.width / (float)scene.height;

// 使用这个变量作为眼睛的位置来开始你的光线。
Vector3f eye_pos(0);
int m = 0;
for (int j = 0; j < scene.height; ++j)
{
for (int i = 0; i < scene.width; ++i)
{
/*
TODO:找到当前像素的x和y位置,以获得通过它的方向矢量。
此外,不要忘记将它们与变量*scale*相乘,并将x(水平)变量与*imageAspectRatio*相乘
*/
float x = (2.0 * i / scene.width - 1.0) * scale * imageAspectRatio;
float y = (1.0 - 2.0 *j / scene.height) * scale;

// 别忘了归一化这个方向
Vector3f dir = Vector3f(x, y, -1); // Don't forget to normalize this direction!
dir = normalize(dir);

// 调用 castRay 来获取最终的颜色
framebuffer[m++] = castRay(eye_pos, dir, scene, 0);
}
// 输出一下?
UpdateProgress(j / (float)scene.height);
}

// 将缓冲区的颜色保存到文件中(帧缓冲区中的信息将被保存为图像)
FILE* 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);
}

Triangle.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
判断射线是否和三角形相交
用 Moller Trumbore 算法,这个直接套公式解出来就行
*/
bool rayTriangleIntersect(const Vector3f& v0, const Vector3f& v1, const Vector3f& v2, const Vector3f& orig,
const Vector3f& dir, float& tnear, float& u, float& v)
{
Vector3f E1 = v1 - v0;
Vector3f E2 = v2 - v0;
Vector3f S = orig - v0;
Vector3f S1 = crossProduct(dir, E2);
Vector3f S2 = crossProduct(S, E1);

float t = dotProduct(S2,E2) / dotProduct(S1,E1);
float b1 = dotProduct(S1,S) / dotProduct(S1,E1);
float b2 = dotProduct(S2,dir) / dotProduct(S1,E1);

// 都 >0 才表示有解
if(t > 0 && b1 > 0 && b2 > 0 && 1 - (b1 + b2) > 0)
{
tnear = t;
u = b1;
v = b2;
return true;
}

return false;
}

光线追踪结果:

欢迎关注我的其它发布渠道