c++ - OpenGL 法线贴图问题 - 法线可能朝向错误的方向?

标签 c++ opengl glsl normals

我目前正在开发我的第一个基于 OpenGL 的游戏引擎。我需要法线贴图作为一项功能,但它无法正常工作。

Here is an animation of what is Happening

伪影受光线与表面法线之间的角度影响。相机移动不会以任何方式影响它。我也(至少现在)采用效率较低的方法,将从法线贴图中提取的法线转换为 View 空间,而不是将所有内容转换为切线空间。

以下是我的代码的相关部分:

生成切线和副切线

        for(int k=0;k<(int)mb->getIndexCount();k+=3)
        {
            unsigned int i1 = mb->getIndex(k);
            unsigned int i2 = mb->getIndex(k+1);
            unsigned int i3 = mb->getIndex(k+2);

            JGE_v3f v0 = mb->getVertexPosition(i1);
            JGE_v3f v1 = mb->getVertexPosition(i2);
            JGE_v3f v2 = mb->getVertexPosition(i3);

            JGE_v2f uv0 = mb->getVertexUV(i1);
            JGE_v2f uv1 = mb->getVertexUV(i2);
            JGE_v2f uv2 = mb->getVertexUV(i3);

            JGE_v3f deltaPos1 = v1-v0;
            JGE_v3f deltaPos2 = v2-v0;
            JGE_v2f deltaUV1 = uv1-uv0;
            JGE_v2f deltaUV2 = uv2-uv0;

            float ur = deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x;

            if(ur != 0)
            {
                float r = 1.0 / ur;

                JGE_v3f tangent;
                JGE_v3f bitangent;

                tangent = ((deltaPos1 * deltaUV2.y) - (deltaPos2 * deltaUV1.y)) * r;
                tangent.normalize();

                bitangent = ((deltaPos1 * -deltaUV2.x) + (deltaPos2 * deltaUV1.x)) * r;
                bitangent.normalize();

                tans[i1] += tangent;
                tans[i2] += tangent;
                tans[i3] += tangent;
                btans[i1] += bitangent;
                btans[i2] += bitangent;
                btans[i3] += bitangent;
            }
        }

Here's a picture of the Tangents

在Vertex Shader中计算TBN矩阵 (mNormal 校正非均匀尺度的法线)

vec3 T = normalize((mVW * vec4(tangent, 0.0)).xyz);
tnormal = normalize((mNormal * n).xyz);
vec3 B = normalize((mVW * vec4(bitangent, 0.0)).xyz);

tmTBN = transpose(mat3(
T.x, B.x, tnormal.x,
T.y, B.y, tnormal.y,
T.z, B.z, tnormal.z));

最后是我使用法线贴图中的采样法线并尝试将其转换为片段着色器中的 View 空间

fnormal = normalize(nmapcolor.xyz * 2.0 - 1.0);
fnormal = normalize(tmTBN * fnormal);

“nmapcolor”是从法线贴图中采样的颜色。 然后在照明计算中像正常一样使用“fnormal”。

长期以来我一直在努力解决这个问题,但完全不知道如何让它发挥作用。任何帮助将不胜感激。

编辑 - 我稍微修改了代码以在世界空间中工作并输出结果。大平台没有法线贴图(并且可以正常工作),而小平台有。 World Space Normals

我添加了法线朝向的方向。它们通常应该是相同的颜色,但它们明显不同。似乎 mTBN 矩阵没有正确地将切线空间法线转换为世界(和正常 View )空间。

最佳答案

嗯...我解决了这个问题。事实证明我的法线贴图实现是完美的。问题实际上出在我的纹理类中。当然,这是我第一次编写 OpenGL 渲染引擎,我没有意识到纹理类中的 unlock() 函数将我的所有纹理保存为 GL_SRGB_ALPHA,包括法线贴图。只有漫射贴图纹理应该是 GL_SRGB_ALPHA。暂时强制所有纹理加载为 GL_RGBA 解决了这个问题。 不敢相信我有这个问题 11 个月了,才发现它是如此之小。

关于c++ - OpenGL 法线贴图问题 - 法线可能朝向错误的方向?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41421909/

相关文章:

c++ - 词法分析

c++ - VS 2008 和 VS 2017 之间的 Visual C++ 内存管理变化

opengl - 如何在 Ubuntu 上获取 "man glRotate"中的 OpenGL 手册页?

c++ - 为什么我的 GLSL 着色器编译失败且没有错误消息?

OpenGL/GLSL - 使用带有多个源的 glShaderSource 来支持包含文件

c++ - 析构函数和python

cocoa - 使用 Alpha 渲染纹理的问题

c++ - 在 GLSL(330 或其他)中,什么会导致统一结构的行为不同于可变结构?

glsl - 鱼眼天空盒着色器

c++ - 使用 PoDoFo 构建 PdfXObject