C中最小光线追踪器的神秘问题
Mysterious problem with minimal ray tracer in C
我正在用 C 编写一个最小的光线追踪器,不久前我写了一个光线追踪器,所以我了解它们背后的理论,只是想重写以进行清理。
我有光线追踪器的必要元素,仅此而已。我写了三角形交集,将像素 space 坐标转换为 NDC(考虑了宽高比和 FOV),并写出了帧缓冲区。
但是,它没有按预期工作。当它应该渲染单个三角形时,图像完全是黑色的。我已经测试过编写单个测试像素,它工作正常,所以我知道这不是图像编写代码的问题。
我已经对数学背后的代码进行了双重和三次检查,对我来说它看起来不错。交集代码基本上是原始 Moller-Trumbore 论文中源代码的副本:
/* ray triangle intersection */
bool ray_triangle_intersect(double orig[3], double dir[3], double vert0[3],
double vert1[3], double vert2[3], double* t, double* u, double* v) {
double edge1[3], edge2[3];
double tvec[3], pvec[3], qvec[3];
double det, inv_det;
/* edges */
SUB(edge1, vert1, vert0);
SUB(edge2, vert2, vert0);
/* determinant */
CROSS(pvec, dir, edge2);
/* ray in plane of triangle if near zero */
det = DOT(edge1, pvec);
if(det < EPSILON)
return 0;
SUB(tvec, orig, vert0);
inv_det = 1.0 / det;
/* calculate, check bounds */
*u = DOT(tvec, pvec) * inv_det;
if(*u < 0.0 || *u > 1.0)
return 0;
CROSS(qvec, tvec, edge1);
/* calculate, check bounds */
*v = DOT(dir, qvec) * inv_det;
if(*v < 0.0 || *u + *v > 1.0)
return 0;
*t = DOT(edge2, qvec) * inv_det;
return 1;
}
CROSS
、DOT
和 SUB
只是宏:
#define CROSS(v,v0,v1) \
v[0] = v0[1] * v1[2] - v0[2] * v1[1]; \
v[1] = v0[2] * v1[0] - v0[0] * v1[2]; \
v[2] = v0[0] * v1[1] - v0[1] * v1[0];
#define DOT(v0,v1) (v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2])
/* v = v0 - v1 */
#define SUB(v,v0,v1) \
v[0] = v0[0] - v1[0]; \
v[1] = v0[1] - v1[1]; \
v[2] = v0[2] - v1[2];
转换代码如下:
double ndc[2];
screen_to_ndc(x, y, &ndc[0], &ndc[1]);
double dir[3];
dir[0] = ndc[0] * ar * tfov;
dir[1] = ndc[1] * tfov;
dir[2] = -1;
norm(dir);
和screen_to_ndc
:
void screen_to_ndc(unsigned int x, unsigned int y, double* ndcx, double* ndcy) {
*ndcx = 2 * (((double) x + (1.0 / 2.0)) / (double) WIDTH) - 1;
*ndcy = 1 - 2 * (((double) y + (1.0 / 2.0)) / (double) HEIGHT);
}
如有任何帮助,我们将不胜感激。
尝试反转三角形的方向。您的光线-三角形相交代码会剔除背面,因为当 det
为负时它 returns 早。
我正在用 C 编写一个最小的光线追踪器,不久前我写了一个光线追踪器,所以我了解它们背后的理论,只是想重写以进行清理。
我有光线追踪器的必要元素,仅此而已。我写了三角形交集,将像素 space 坐标转换为 NDC(考虑了宽高比和 FOV),并写出了帧缓冲区。
但是,它没有按预期工作。当它应该渲染单个三角形时,图像完全是黑色的。我已经测试过编写单个测试像素,它工作正常,所以我知道这不是图像编写代码的问题。
我已经对数学背后的代码进行了双重和三次检查,对我来说它看起来不错。交集代码基本上是原始 Moller-Trumbore 论文中源代码的副本:
/* ray triangle intersection */
bool ray_triangle_intersect(double orig[3], double dir[3], double vert0[3],
double vert1[3], double vert2[3], double* t, double* u, double* v) {
double edge1[3], edge2[3];
double tvec[3], pvec[3], qvec[3];
double det, inv_det;
/* edges */
SUB(edge1, vert1, vert0);
SUB(edge2, vert2, vert0);
/* determinant */
CROSS(pvec, dir, edge2);
/* ray in plane of triangle if near zero */
det = DOT(edge1, pvec);
if(det < EPSILON)
return 0;
SUB(tvec, orig, vert0);
inv_det = 1.0 / det;
/* calculate, check bounds */
*u = DOT(tvec, pvec) * inv_det;
if(*u < 0.0 || *u > 1.0)
return 0;
CROSS(qvec, tvec, edge1);
/* calculate, check bounds */
*v = DOT(dir, qvec) * inv_det;
if(*v < 0.0 || *u + *v > 1.0)
return 0;
*t = DOT(edge2, qvec) * inv_det;
return 1;
}
CROSS
、DOT
和 SUB
只是宏:
#define CROSS(v,v0,v1) \
v[0] = v0[1] * v1[2] - v0[2] * v1[1]; \
v[1] = v0[2] * v1[0] - v0[0] * v1[2]; \
v[2] = v0[0] * v1[1] - v0[1] * v1[0];
#define DOT(v0,v1) (v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2])
/* v = v0 - v1 */
#define SUB(v,v0,v1) \
v[0] = v0[0] - v1[0]; \
v[1] = v0[1] - v1[1]; \
v[2] = v0[2] - v1[2];
转换代码如下:
double ndc[2];
screen_to_ndc(x, y, &ndc[0], &ndc[1]);
double dir[3];
dir[0] = ndc[0] * ar * tfov;
dir[1] = ndc[1] * tfov;
dir[2] = -1;
norm(dir);
和screen_to_ndc
:
void screen_to_ndc(unsigned int x, unsigned int y, double* ndcx, double* ndcy) {
*ndcx = 2 * (((double) x + (1.0 / 2.0)) / (double) WIDTH) - 1;
*ndcy = 1 - 2 * (((double) y + (1.0 / 2.0)) / (double) HEIGHT);
}
如有任何帮助,我们将不胜感激。
尝试反转三角形的方向。您的光线-三角形相交代码会剔除背面,因为当 det
为负时它 returns 早。