光线追踪中的错误UV

3
我有一个关于我的光线追踪程序的问题。图像看起来不对。以下是输出图像:

out

重心坐标和碰撞计算代码如下:

bool CTriangle::Intersect(Calculus::CRay& ray, CIntersection* isect) const {
// Möller–Trumbore intersection algorithm
const Calculus::CPoint3<float>& p1 = v_points[0];
const Calculus::CPoint3<float>& p2 = v_points[1];
const Calculus::CPoint3<float>& p3 = v_points[2];

Calculus::CVector3<float> e1 = p2 - p1;
Calculus::CVector3<float> e2 = p3 - p1;
Calculus::CVector3<float> s1 = Calculus::Math::Cross(ray.direction, e2);
float determinant = Calculus::Math::Dot(s1, e1);

if (determinant == 0.0f)
    return false;

float inv_determinant = 1.0f / determinant;

Calculus::CVector3<float> s = ray.origin - p1;
float b1 = Calculus::Math::Dot(s, s1) * inv_determinant;
if (b1 < 0.0f || b1 > 1.0f)
    return false;

Calculus::CVector3<float> s2 = Calculus::Math::Cross(s, e1);
float b2 = Calculus::Math::Dot(ray.direction, s2) * inv_determinant;
if (b2 < 0.0f || b1 + b2 > 1.0f)
    return false;

float b0 = 1 - b1 - b2;

float thit = Calculus::Math::Dot(e2, s2) * inv_determinant;
if (thit < ray.mint || thit > ray.maxt)
    return false;

isect->p = ray(thit);
isect->n = Calculus::Math::Normalize(Calculus::CVector3<float> 
(v_normals[0].x, v_normals[0].y, v_normals[0].z) * b0 +
    Calculus::CVector3<float>(v_normals[1].x, v_normals[1].y, 
v_normals[1].z) * b1 +
    Calculus::CVector3<float>(v_normals[2].x, v_normals[2].y, 
v_normals[2].z) * b2);
isect->uv = v_uvs[0] * b0 + v_uvs[1] * b1 + v_uvs[2] * b2;
isect->tHit = thit;
isect->ray_epsilon = 1e-5f * thit;

return true;
}

我在光线追踪程序中使用的纹理:(文件类型:bmp)

Texture1

我的obj文件如下。背景形状由两个三角形组成。只对背景形状应用纹理投影:

v  -24.1456 -11.1684 -26.2413
v  24.1455 -11.1684 -26.2413
v  -24.1456 37.1227 -26.2413
v  24.1455 37.1227 -26.2413
# 4 vertices

vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
# 6 vertex normals

vt 0.9995 0.0005 0.0000
vt 0.0005 0.0005 0.0000
vt 0.9995 0.9995 0.0000
vt 0.0005 0.9995 0.0000
# 4 texture coords

o back
g back
usemtl default
s 1
f 1/1/1 2/2/2 4/4/3 
f 4/4/4 3/3/5 1/1/6 
# 2 faces

这是插值UV绘制调用。

enter image description here

这是索引算法,我从零开始:

...
Calculus::CPoint3<unsigned short> p, t, n;
sscanf_s(token, "%hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu",
    &p.x, &t.x, &n.x, &p.y, &t.y, &n.y, &p.z, &t.z, &n.z);
pi.push_back(p);
ti.push_back(t);
ni.push_back(n);
…

index = ti[i].x - 1;
temp_t[0] = vt[index]; // first uv
index = ti[i].y - 1;
temp_t[1] = vt[index]; // second uv
index = ti[i].z - 1;
temp_t[2] = vt[index]; // third uv

我想知道我在哪里犯了错误。谢谢。


尝试将UV绘制为颜色,例如rgb(u,v,0),而不是纹理,看看会发生什么。 - 3Dave
它进行线性插值,但其中一个三角形是绿黄色的,另一个则是红黑色的插值。谢谢。 - user5044221
1
如果其中一个三角形是绿色/黄色的,没有100%的红色和100%的绿色,则您的uv计算是错误的。绘制您的Bary坐标并查看其外观。这是图形调试,或者就像我喜欢称之为:猜测。(另外,我假设您已经注意到您的纹理在您发布的截图中被翻转了。) - 3Dave
你正在从bmp中加载纹理,对吗?在bmp格式中,像素是从左下角开始存储的,因此您需要在uv分配中考虑到这一点,或者更好的方法是将纹理保存在合理的格式中。此外,您的uv绘图显示四边形的右下角为(0,0) uv,其中u向左增加,v向上增加,将(1,1)放在左上角顶点。这是您想要的吗? - 3Dave
通常,我期望 (0,0) 是左上角,(1,1) 是右下角。根据您的UV图像以及该图像是BMP格式,您的输出是正确的。您是如何加载/解码图像的?(如果图像头中的高度为负,则它们从上到下存储) - 3Dave
显示剩余5条评论
1个回答

2
isect->uv = v_uvs[0] * b1 + v_uvs[1] * b2;

这不是顶点属性参数化插值的正确方法:

  • 参数 b1, b2 应用在了错误的顶点上
  • 你没有考虑第三个顶点 v_uvs[2]

正确的版本:

isect->uv = v_uvs[0] * b0 + v_uvs[1] * b1 + v_uvs[2] * b2;

谢谢回答。我没有加代码,因为w是零。我已经更新了代码和输出,但错误仍然存在。 - user5044221
@ADesignersEncyclopedia 你是如何解析OBJ文件的?这可能是一个索引问题。v_uvs的值是多少?你是如何采样纹理的? - meowgoesthedog
@meowgoesthedog v_points = '{{x=-24.1455994 y=-11.1683998 z=-26.2413006 }, {x=24.1455002 y=-11.1683998 z=-26.2413006 }, {x=24.1455002 y=37.1226997 z=-26.2413006 }} v_uvs = {{x=1.00000000 y=0.000000000 }, {x=0.000000000 y=0.000000000 }}' 我正在从bmp文件中获取像素:r = pixels [3 *(x * width + y)并将其他g b值添加+1。 - user5044221
因为 w = 0.0,所以不想添加。 - user5044221
因为我没有使用z(深度)纹理。我想只有u和v就足够了。 - user5044221
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接