不使用Tangent / Bitangent向量的法线贴图

时间:2016-07-18 18:15:34

标签: opengl 3d webgl

不幸的是,许多教程都将TBN矩阵描述为任何类型的法线贴图的事实必须,而没有详细了解为什么会出现这种情况,这使我对某个特定情况感到困惑

让我们假设我需要在屏幕上的简单四边形上应用凹凸/法线贴图,以后可以通过它的正常矩阵进行转换

如果在任何变换前的“静止位置”中四边形的曲面法线正好指向正z方向(opengl),仅仅用模型矩阵变换从正常纹理贴图中读取的矢量是不够的? / p>

vec3 bumpnormal = texture2D(texture, Coord.xy);
bumpnormal = mat3(model) * bumpnormal;  //assuming no scaling occured

我确实理解,如果我们计算立方体上的凹凸正常而不计算具有相同纹理坐标的不同面实际上具有不同方向的情况会如何改变,这引出了我的下一个问题

假设整个模型仅使用单个法线贴图纹理,而不在模型的不同部分重复所述纹理坐标,是否可以保存为每个顶点存储的切线/比特向量的6个浮点数和计算通过简单地用模型的矩阵变换凹凸正常来获得相同结果的TBN矩阵altogheter? 如果是这种情况,为什么它不是首选解决方案?

2 个答案:

答案 0 :(得分:6)

  

如果四边形表面处于正常位置"静止位置"在任何变换精确指向正z方向(opengl)之前,仅仅用模型矩阵转换从普通纹理贴图中读取的矢量是否足够?

没有

让我们说你从法线贴图得到的值是(1,0,0)。这意味着地图中的法线指向右边。

那么......到底是哪里?或者更重要的是,当我们说'#34;对"?

时,我们处于什么空间

现在,您可能会立即认为模型空间中的右侧只是+ X.但问题是,它不是。为什么呢?

由于你的纹理坐标。

如果你的模型空间矩阵在模型空间Z轴周围顺时针旋转90度,你用这个矩阵变换法线,那么你得到的法线应该从(1,0,0)变为(0,-1,0)。这就是预期的结果。

但是如果你有一个面向+ Z的正方形,并且围绕Z轴旋转90度,那么是否应该产生与旋转纹理坐标相同的结果?毕竟,它是定义U和V意味着 relative 到模型空间的纹理坐标。

如果你的方块的右上角纹理坐标是(1,1),左下角是(0,0),那么"右边"在纹理空间意味着"对"在模型空间。但是如果你改变了映射,那么(1,1)位于右下角,而(0,0)位于左上角,那么" right"在纹理空间已成为" down" (-Y)在模型空间。

如果忽略纹理坐标,从模型空间位置到纹理上的位置的映射,那么你的(1,0,0)法线仍将指向"右边"在模型空间。但是你的纹理贴图表明它应该在模型空间中指向下(0,-1,0)。就像你自己旋转模型空间一样。

使用切线空间法线贴图,纹理中存储的法线与纹理在曲面上的映射方式有关。定义从模型空间到切线空间(纹理映射的空间)的映射是TBN矩阵的用途。

随着对象和法线之间的映射变得更加复杂,这变得更加复杂。您可以为四边形的情况伪造它,但对于一般数字,它需要算法。毕竟,映射不是常量。它涉及拉伸和倾斜,因为不同的三角形使用不同的纹理坐标。

现在,有对象空间法线贴图,它可以生成模型空间中显式的法线。这些避免了对切线空间基矩阵的需要。但它将法线贴图与其使用的对象紧密联系在一起。你甚至不能做基本的纹理坐标动画,更不用说允许法线贴图与两个独立的对象一起使用。如果您正在进行骨骼剥皮,它们几乎不可行,因为三角形通常会改变尺寸。

答案 1 :(得分:1)

http://www.thetenthplanet.de/archives/1180

rowMeans

基本上我认为你在描述这种方法。我同意在大多数方面都是优越的。它使后来的计算变得更加干净,而不是变成一堆空间变换。

不是将所有东西都计算到切线的空间中,而是找到正确的世界空间法线。这就是我在项目中使用的内容,我很高兴找到了这种方法。