我正在尝试从网格的细分中计算法线贴图,有 2 个网格,一个包含四边形和三角形的 UV 展开基础网格和一个仅包含四边形的细分网格。
假设我有一个四边形,其中包含对象空间和 UV 空间中顶点的所有坐标(四边形不是平坦的),四边形的面法线和一个像素,它在 UV 空间中的位置。
我可以计算给定四边形的 TBN 矩阵并将颜色写入像素吗,如果是这样,那么四边形是否不同?
我问这个是因为我找不到任何计算四边形的 TBN 矩阵的例子,只有三角形?
在回答您的问题之前,让我首先解释一下您实际需要的切线和双切线是什么。
让我们暂时忘记三角形、四边形或多边形。我们只有一个表面(以任何表示形式给出)和一个纹理坐标形式的参数化,这些坐标在表面上的每个点上定义。然后我们可以将表面定义为:xyz = s(uv)
。uv
是一些 2D 纹理坐标,s
将这些纹理坐标转换为 3D 世界位置的功能xyz
。现在,切线是 u 坐标增加的方向。即,它是 3D 位置相对于 u 坐标的导数:T = d s(uv) / du
。类似地,双切线是相对于 v 坐标的导数。法线是垂直于两者的向量,通常指向外部。请记住,这三个向量通常在表面上的每个点都不同。
现在让我们转到离散计算机图形学,其中我们用多边形网格近似我们的连续表面s
。问题是没有办法再得到确切的切线和双切线了。我们只是在离散近似中丢失了很多信息。因此,无论如何,有三种常见的方法可以近似切线:
- 将向量与模型一起存储(通常不会这样做)。
- 估计顶点处的向量并将其插值到面中。
- 分别计算每个面的矢量。这将为您提供一个不连续的切线空间,当两个相邻面之间的二面角太大时,会产生伪影。尽管如此,这显然是大多数人正在做的事情。这显然也是你想做的。
让我们专注于第三种方法。对于三角形,这尤其简单,因为纹理坐标在三角形上线性插值(重心插值)。因此,导数都是常数(它只是一个线性函数)。这就是为什么您可以计算每个三角形的切线/双切线。
对于四边形来说,这不是那么简单。首先,您必须就从四边形顶点到其内部插值位置和纹理坐标的方法达成一致。通常,使用双线性插值。但是,这不是线性插值,即切线和双切线将不再恒定。这只会在特殊情况下发生(如果四边形是平面的,而 UV 空间中的四边形是平行四边形)。通常,这些假设不成立,并且对于四边形上的每个点,您最终会得到不同的切线/双切线/法线。
计算所需导数的一种方法是引入辅助坐标系。让我们定义一个坐标系st
,其中四边形的第一个角具有坐标(0, 0)
,对角线相对的角具有(1, 1)
(其他角具有(0, 1)
和(1, 0)
)。这些实际上是我们的插值坐标。因此,给定任意插值方案,计算导数d xyz / d st
和d uv / d st
相对简单。第一个将是 3x2 矩阵,第二个将是 2x2 矩阵(这些矩阵称为插值的雅可比矩阵)。然后,给定这些矩阵,您可以计算:
d xyz / d uv = (d xyz / d st) * (d st / d uv) = (d xyz / d st) * (d uv / d st)^-1
这将为您提供一个 3x2 矩阵,其中第一列是切线,第二列是双切线。