gpt4 book ai didi

c++ - 计算 3D 切线空间

转载 作者:搜寻专家 更新时间:2023-10-31 01:23:28 27 4
gpt4 key购买 nike

为了在 GLSL 着色器中使用法线贴图,您需要知道每个顶点的法线、切线和副切线 vector 。 RenderMonkey 通过为此提供它自己的预定义变量(rm_tangentrm_binormal)使这变得容易。我正在尝试将此功能添加到我自己的 3d 引擎中。显然,可以使用每个顶点的 xyz 坐标、uv 纹理坐标和法 vector 来计算三角形中每个顶点的切线和双切线。经过一番搜索后,我设计了这个函数来计算三角形结构中每个顶点的切线和副切线。

void CalculateTangentSpace(void) {
float x1 = m_vertices[1]->m_pos->Get(0) - m_vertices[0]->m_pos->Get(0);
float x2 = m_vertices[2]->m_pos->Get(0) - m_vertices[0]->m_pos->Get(0);
float y1 = m_vertices[1]->m_pos->Get(1) - m_vertices[0]->m_pos->Get(1);
float y2 = m_vertices[2]->m_pos->Get(1) - m_vertices[0]->m_pos->Get(1);
float z1 = m_vertices[1]->m_pos->Get(2) - m_vertices[0]->m_pos->Get(2);
float z2 = m_vertices[2]->m_pos->Get(2) - m_vertices[0]->m_pos->Get(2);

float u1 = m_vertices[1]->m_texCoords->Get(0) - m_vertices[0]->m_texCoords->Get(0);
float u2 = m_vertices[2]->m_texCoords->Get(0) - m_vertices[0]->m_texCoords->Get(0);
float v1 = m_vertices[1]->m_texCoords->Get(1) - m_vertices[0]->m_texCoords->Get(1);
float v2 = m_vertices[2]->m_texCoords->Get(1) - m_vertices[0]->m_texCoords->Get(1);

float r = 1.0f/(u1 * v2 - u2 * v1);

Vec3<float> udir((v2 * x1 - v1 * x2) * r, (v2 * y1 - v1 * y2) * r, (v2 * z1 - v1 * z2) * r);
Vec3<float> vdir((u1 * x2 - u2 * x1) * r, (u1 * y2 - u2 * y1) * r, (u1 * z2 - u2 * z1) * r);

Vec3<float> tangent[3];
Vec3<float> tempNormal;

tempNormal = *m_vertices[0]->m_normal;
tangent[0]=(udir-tempNormal*(Vec3Dot(tempNormal, udir)));
m_vertices[0]->m_tangent=&(tangent[0].Normalize());
m_vertices[0]->m_bitangent=Vec3Cross(m_vertices[0]->m_normal, m_vertices[0]->m_tangent);

tempNormal = *m_vertices[1]->m_normal;
tangent[1]=(udir-tempNormal*(Vec3Dot(tempNormal, udir)));
m_vertices[1]->m_tangent=&(tangent[1].Normalize());
m_vertices[1]->m_bitangent=Vec3Cross(m_vertices[1]->m_normal, m_vertices[1]->m_tangent);

tempNormal = *m_vertices[2]->m_normal;
tangent[2]=(udir-tempNormal*(Vec3Dot(tempNormal, udir)));
m_vertices[2]->m_tangent=&(tangent[2].Normalize());
m_vertices[2]->m_bitangent=Vec3Cross(m_vertices[2]->m_normal, m_vertices[2]->m_tangent);
}

当我使用此函数并将计算出的值发送到我的着色器时,模型看起来几乎与在 RenderMonkey 中所做的一样,但它们以一种非常奇怪的方式闪烁。我将问题追溯到发送 OpenGL 的切线和副切线。这让我怀疑我的代码做错了什么。任何人都可以看到任何问题或对尝试其他方法有任何建议吗?

我还应该指出,上面的代码非常 hacky,我对背后的数学原理知之甚少。

最佳答案

找到解决方案。更简单(但仍然有点老套)的代码:

void CalculateTangentSpace(void) {
float x1 = m_vertices[1]->m_pos->Get(0) - m_vertices[0]->m_pos->Get(0);
float y1 = m_vertices[1]->m_pos->Get(1) - m_vertices[0]->m_pos->Get(1);
float z1 = m_vertices[1]->m_pos->Get(2) - m_vertices[0]->m_pos->Get(2);

float u1 = m_vertices[1]->m_texCoords->Get(0) - m_vertices[0]->m_texCoords->Get(0);

Vec3<float> tangent(x1/u1, y1/u1, z1/u1);
tangent = tangent.Normalize();

m_vertices[0]->m_tangent = new Vec3<float>(tangent);
m_vertices[1]->m_tangent = new Vec3<float>(tangent);
m_vertices[2]->m_tangent = new Vec3<float>(tangent);

m_vertices[0]->m_bitangent=new Vec3<float>(Vec3Cross(m_vertices[0]->m_normal, m_vertices[0]->m_tangent)->Normalize());
m_vertices[1]->m_bitangent=new Vec3<float>(Vec3Cross(m_vertices[1]->m_normal, m_vertices[1]->m_tangent)->Normalize());
m_vertices[2]->m_bitangent=new Vec3<float>(Vec3Cross(m_vertices[2]->m_normal, m_vertices[2]->m_tangent)->Normalize());
}

关于c++ - 计算 3D 切线空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1351129/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com