2013-03-10 139 views
6

我只是想知道我的理解TBN矩阵计算正确法线贴图,TBN矩阵计算

在顶点着色器,我们通常使用:

vec3 n = normalize(gl_NormalMatrix * gl_Normal); 
vec3 t = normalize(gl_NormalMatrix * Tangent.xyz); 
vec3 b = normalize(gl_NormalMatrix * Bitangent.xyz); 
mat3 tbn = mat3(t, b, n); 

据我了解这个tbn矩阵从变换的矢量Tangent space to Eye space。实际上,我们想要反转 - 从眼睛空间向Tangent空间转换矢量。因此,我们需要反转tbn矩阵:

tbn = transpose(tbn); // transpose should be OK here for doing matrix inversion 

注:tbn - 应该只包含旋转,对于这种情况下,我们可以使用转逆矩阵。

我们可以改变我们的载体:

vec3 lightT = tbn * light_vector; 
...   = tbn * ... 

在几个教程,源代码中我发现,作者用这样的:

light.x = dot(light, t); 
light.y = dot(light, b); 
light.z = dot(light, n); 

上面的代码不一样乘以由transposed(tbn)矩阵组成。

问题:

我们应该用换位tbn矩阵正如我上面所解释的?或者我错过了什么?

注解通过该解决方案,我们将矢量(light_vector)转换为顶点着色器中的TBN,然后在片段着色器中我们只需从法线贴图中获得法线。其他选项是创建从TBN空间转换到眼图空间的TBN矩阵,然后在片段着色器中从法线贴图转换每个读取法线。

+0

定义“正确的“?你把你的正常和切向量的交叉乘积拿到你的苦味矢量。一般来说,这对于大多数表面来说*不是正确的。对你来说这可能是正确的,但大多数纹理映射不使用完美的正交映射到曲面。 – 2013-03-10 21:54:08

+0

对,我已经更新了这个问题。我也改变了不安的计算方式。 – fen 2013-03-11 08:01:47

回答

0

转置不是矩阵的倒置!!!

在顶点着色器我的TBN矩阵是这样的:

uniform mat4x4 tm_l2g_dir; 
layout(location=3) in vec3 tan; 
layout(location=4) in vec3 bin; 
layout(location=5) in vec3 nor; 
out smooth mat3 pixel_TBN; 

void main() 
{ 
    vec4 p; 
    //... 
    p.xyz=tan.xyz; p.w=1.0; pixel_TBN[0]=normalize((tm_l2g_dir*p).xyz); 
    p.xyz=bin.xyz; p.w=1.0; pixel_TBN[1]=normalize((tm_l2g_dir*p).xyz); 
    p.xyz=nor.xyz; p.w=1.0; pixel_TBN[2]=normalize((tm_l2g_dir*p).xyz); 
    //... 
} 

其中:

  • tm_l2g_dir是从局部模型空间,以世界舞台的空间变换矩阵whitout任何运动(改变只向)你的代码它是你的正常矩阵
  • tan,bin,TBN矩阵的矢量(作为我的模型的一部分)

也不 - 是法线矢量从实际顶点位置到表面(可以计算从该顶点的两个顶点的矢量乘法)

棕褐色,箱是垂直载体通常平行于纹理映射轴系或模型的teselation。如果选择错误的tan/bin向量,则有时会出现一些照明伪影。例如,如果你有气缸比仓是其旋转轴和黄褐色是垂直于它沿着圆(正切)

棕褐色,bin中,也不应垂直于彼此

就可以计算出TBN也自动但这会导致一些文物。要做到这一点,你只需选择用于正常的计算和斌=也不X斌为棕褐色矢量一个顶点

在片段着色器

我使用pixel_TBN与法线贴图来计算真​​正的正常片段

//------------------------------------------------------------------ 
#version 420 core 
//------------------------------------------------------------------ 
in smooth vec2 pixel_txr; 
in smooth mat3 pixel_TBN; 
uniform sampler2D txr_normal; 
out layout(location=0) vec4 frag_col; 
const vec4 v05=vec4(0.5,0.5,0.5,0.5); 
//------------------------------------------------------------------ 
void main(void) 
    { 
    vec4 col; 
    vec3 normal; 
    col=(texture2D(txr_normal,pixel_txr.st)-v05)*2.0;  // normal/bump maping 
    normal=pixel_TBN*col.xyz; 
    // col=... other stuff to compute col 

    frag_col=col; 
    } 
//------------------------------------------------------------------ 
+1

你在片段着色器中如何处理pixel_TBN?据我所知,您可以将tan,bin或Tangent Space转换为全局场景空间。对于只包含旋转的矩阵,可以使用转置进行反演。 – fen 2013-08-07 07:09:36

+0

只是为你编辑了简单的部分片段。在每个片段正常情况下,您可以执行任何操作(任何照明模型,从立方体贴图添加铬反射...) – Spektre 2013-08-08 22:25:37

+2

正常3x3的转置也是相反的。也许这就是原来的海报所指的? – Tommy 2013-08-08 22:43:11