许多映射技术(包括法线凹凸贴图,视差贴图等)都需要特殊的逐顶点切线空间基础(正切,法线,副法线/比特点)。
这显然意味着我的模型不仅要导出顶点位置,纹理坐标和近似每顶点法线,还要导出其中一个切线空间基矢量(通常为tangent
),因为另一个可以使用cross(tangent, normal)
直接在着色器中找到。
请注意,position,normal,uv和tange实际上以下列方式相互依赖(您必须知道关于顶点的所有其他内容以准备切线基础)。
position -> normal -> tangents
uv ->
现在 - 在现代3D游戏/渲染引擎中如何处理这类事情?
他们实际上是为每个顶点提供法线,切线和 uv坐标,还是可以在运行时以某种方式计算它们?它们应该是模型数据的一部分还是应该是仅运行时属性?
我也知道当使用几何着色器使用Direct3D10+
时,可以在运行时直接准备法线和切线(显然,因为我们可以访问每个三角形中的顶点) - 是值得或者这些东西总是预先计算?
答案 0 :(得分:6)
我的观点如下:
UV坐标:明确预先计算。复杂模型的UV展开不是一项简单的算法任务,通常涉及手动放置接缝以获得最佳结果。 此外,如果您的模型带有纹理外观,则UV需要与外观匹配,因此在这种情况下,它们可能无法在运行时计算。
法线理论上你可以在加载过程中在几何着色器甚至CPU上预先计算它们。但有一件事:游戏中的真实模型通常不是原始模型,而是具有较低多边形数的版本。在游戏中使用的最终模型中,你有较少的顶点,但是每顶点从原始的高多边形模型(也用于环境遮挡计算等)更准确地计算法线。因此,预先计算法线也是可行的。
此外,在许多游戏中,为每个模型的颜色纹理提供纹理与每个纹素法线贴图(通常在切线空间中,AFAIK),以便稍后进行平行贴图。像素着色器。
因此看起来我的建议很明确 - 去预先计算数据,有更好的细节并节省着色器处理或加载时间 - 除非您需要担心模型大小(即GPU内存)限制) - 只有在几何着色器中计算法线才能节省一些空间。
答案 1 :(得分:3)
通常,您需要尽可能预先计算。大多数引擎都有一个自定义编写的工具,可以从3D软件中获取原始数据,并将其按照运行时的格式(添加切线和bitangents等)。 然而... 的
在某些情况下,每顶点内存开销可能是一个特定的性能问题。这是因为移动有关系统的数据会产生开销 - 它是“隐藏的”,因为它不是一个明确的添加到着色器中的指令,所以它更先进一些。
在这些情况下, bitangent 可能不会预先计算,而是在运行时构造(以减少内存中顶点的大小)。 Bitangents 适用于此,因为它们可以通过普通,切线和方向性标志构建 - 是单个顶点的所有属性。
法线,某些 UV映射以及其他需要了解网格“拓扑”的内容 - 此拓扑通常不会出现在运行时数据中。他们还需要艺术家的额外标记;像锋利的边缘和纹理接缝等。出于这个原因,法线, UVs 和第一个切线几乎总是预先计算好所有但非常特殊类型的几何。
请记住,Max,Maya或Blender中的模型表示与运行时版本非常不同。
编辑软件
运行时(适用于DirectX,OpenGL等)
通常,您会丢失大量无法重建的信息。如果您使用原始Max / Maya版本的几何体尽可能多地做您的艺术家将是最快乐的。
答案 2 :(得分:2)
您也可以使用D3D9中的ID3DXMesh执行此操作。您应该始终提前计算它们 - 因为在运行时再次计算它们是浪费的。但是,对于每个网格,你只需要计算一次,所以除非你的程序在程序上生成网格,否则它可能不会在何时何地完成。
这里唯一重要的是在CPU而不是GPU上计算它们,因为你每次都在GPU上一次又一次地做这项工作,与CPU上的一次相比,这是完全浪费。据我所知,所有3D渲染系统都会在CPU上计算法线等,将其保存到文件中,然后将其加载并发送到GPU进行工作。
答案 3 :(得分:1)
我更喜欢预先计算它们,因为您需要对接缝,镜像纹理,包装等进行特殊处理。
在运行时计算它并不是完全无关紧要的,因为您可能需要比当前三角形数据更多来获得正确的切线空间。
答案 4 :(得分:0)
UV和法线通常在艺术家的控制之下。可以使用UV的梯度来计算切线和副法线。一直计算切线和副法线往往有点贵,因此通常会根据基础几何图形对它们进行一次预先计算。最好在发货之前减少装载时间。