You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

光栅化法线贴图代码转光线追踪closest hit着色器结果不一致排查

代码问题排查点
  • TBN矩阵转置错误
    原光栅化代码中构造的mat3(T, B, N)本身就是「切线空间→世界空间」的变换矩阵,无需额外转置。你当前代码加了transpose后,矩阵变为「世界空间→切线空间」,和需求完全相反,这是最核心的错误。
  • 副切线符号不匹配
    原光栅化代码中副切线B的计算为-normalize(cross(N, T)),你需要确认顶点数据中存储的BiTangant是否和这个符号一致:如果顶点烘焙的副切线是cross(N, T)得到的,就会和原逻辑符号相反,导致法线沿切线平面翻转。
  • 法线变换未使用逆转置矩阵
    如果你的模型存在非均匀缩放,直接用模型变换矩阵的mat3部分变换法线/切线/副切线会导致向量方向偏移,正确的法线变换矩阵应该是模型变换矩阵的逆矩阵的转置。
  • 辅助校验点
    可以先去掉法线贴图逻辑,直接返回插值的顶点法线,确认光照基础逻辑正确后再调试法线贴图部分;同时确认法线贴图的存储格式是否符合约定,比如是否需要翻转G通道适配当前坐标系。
修正后参考代码
vec3 getNormalFromMap(MaterialInfo material, Vertex vertex)
{
    // 法线变换矩阵(逆转置)可移到CPU侧预计算传入,减少着色器运行开销
    mat3 normalMatrix = transpose(inverse(mat3(
        meshProperties[gl_InstanceCustomIndexEXT].ModelTransform 
        * MeshTransform[gl_InstanceCustomIndexEXT].Transform
    )));
    vec3 T = normalize(normalMatrix * vertex.tangent);
    vec3 N = normalize(normalMatrix * vertex.normal);
    // 正交化切线保证T和N垂直,避免网格变形带来的误差
    T = normalize(T - dot(T, N) * N);
    // 按原光栅化逻辑计算副切线,和原代码符号对齐,也可以用顶点存储的B校验符号一致性
    vec3 B = -normalize(cross(N, T));
    
    // 移除多余的transpose,直接构造切线空间转世界空间的矩阵
    mat3 TBN = mat3(T, B, N);

    vec3 tangentNormal = texture(TextureMap[material.NormalMapID], vertex.uv).xyz;
    tangentNormal = normalize(tangentNormal * 2.0 - 1.0);
    
    return normalize(TBN * tangentNormal);
}

内容的提问来源于stack exchange,提问作者klj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 16:48:03