切线、副法线和其他与着色器相关的东西
许多贴图技术,包括法线凹凸贴图、视差贴图等都需要特殊的每顶点切线空间基础(切线、法线、副法线/双切线)。
这显然意味着我的模型不仅应该导出顶点位置、纹理坐标和近似的每顶点法线,而且还应该导出切线空间之一基向量(通常是切线
),因为另一个可以使用cross(tangent, normal)
直接在着色器中找到。
请注意,位置、法线、uv 和切线实际上以以下方式相互依赖(您必须了解有关顶点的所有其他信息才能准备切线基础)。
position -> normal -> tangents
uv ->
现在 - 此类事情是如何处理的在现代 3D 游戏/渲染引擎中?
它们是否真的提供每个顶点的法线、切线和uv坐标,或者它们可以在运行时以某种方式计算吗?它们应该是模型数据的一部分还是应该是仅运行时的属性?
我也知道,当使用 Direct3D10+
使用几何着色器时,实际上可以准备法线和切线在运行时正确(显然,因为我们可以访问每个三角形中的顶点)-值得还是应该始终预先计算这些东西?
Many of the mapping techniques including normal bump mapping, parallax mapping and others require the special per-vertex tangent-space basis (tangent, normal, binormal / bitangent).
This obviously means that my models should not only export vertex positions, texture coordinates and approximated per-vertex normals, but also one of the tangent space basis vectors (usually tangent
), because the other one can be found directly in the shader using cross(tangent, normal)
.
Note that position, normal, uv and tangents actually depend on each other the following way (you have to know everything else about the vertex to prepare the tangent basis).
position -> normal -> tangents
uv ->
Now - how is this sort of things handled in modern 3D games / rendering engines?
Do they actually supply the normals, tangents and the uv coordinates per each vertex or can they somehow be calculated in runtime? Should they be the part of the model data or should they be a runtime-only property?
I also know that when using Direct3D10+
using the geometry shaders one can actually prepare the normals and the the tangents right in runtime (obviously, because we have access to the vertices in each triangle) - is it worth it or should these things be always precomputed?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我的观点如下:
UV坐标:显然是预先计算的。复杂模型的 UV 展开并不是一项微不足道的算法任务,通常需要手动放置接缝以获得最佳结果。
另外,如果您的模型带有纹理皮肤,则 UV 需要与皮肤匹配,因此在这种情况下,它们可能不会在运行时计算。
法线:理论上,您可以在几何着色器中甚至在加载期间在 CPU 上预先计算它们。但有一件事:游戏中的真实模型通常不是原始模型,而是多边形数量较少的版本。在游戏中使用的最终模型中,顶点数较少,但每个顶点的顶点数较少。法线是从原始高多边形模型(也用于环境光遮挡计算等)更准确地计算出来的。因此,预先计算法线也是可行的。
此外,在许多游戏中,带有每个纹理元素法线贴图的纹理(通常在切线空间中,据我所知)与每个模型的颜色纹理一起提供,以便稍后在像素着色器中进行并行映射。
因此,看起来我的建议很明确 - 使用预先计算的数据,拥有更好的细节并节省着色器处理或加载时间 - 除非您需要担心模型大小(即 GPU 内存限制) -只有这样在几何着色器中计算法线才能节省一些空间。
My view is as follows:
UV coordinates: clearly precomputed. UV unwrapping of a complex model is not a trivial, algorithmic task and usually involves manual placing of seams for best result.
Also, if your model comes with a texture skin, then the UVs need to match the skin, so in this case they may not be computed during runtime.
Normals: theoretically you could precompute them in a geometry shader or even on CPU during loading. But there's one thing: the real models in games are often NOT the original models, but versions with lower polygon count. In the final model used in-game, you have less vertices, but the per-vertex normals are calcuated more accurately from the original high-poly model (which is also used for ambient occlusion calculation, etc). Therefore, having the normals precalculated is also feasible.
Also, in many games a texture with per-texel normal map (usually in tangent space, AFAIK) is provided together with the color texture for each model, for the purposes of parallel mapping later in the pixel shader.
Therefore it looks like my suggestion is clear - go for precomputed data, have better details and save on either shader processing or loading time - unless you need to worry about the model size (i.e. GPU memory limit) - only then having normals calculated in geometry shader would save you some space.
一般来说,您会希望尽可能多地进行预先计算。大多数引擎都会有一个自定义的编写工具,可以从 3D 软件中获取原始数据,并将其转换为运行时的格式(添加切线和双切线等)。 但是...
在某些情况下,每个顶点的内存开销可能是一个特殊的性能问题。这是因为存在与移动系统数据相关的开销——它是“隐藏的”,因为它不是显式的添加到着色器中的指令,因此它更高级一些。
在这些情况下,双切线可能不会预先计算,而是在运行时构建(以减少内存中顶点的大小)。 双切线适合于此,因为它们可以从法线、切线和方向性标志构建 - 这都是单个顶点的属性。
法线、一些UV映射和其他东西需要了解网格的“拓扑”——而这种拓扑通常不会出现在运行时数据中。它们还需要艺术家的额外标记;例如锐边和纹理接缝等。因此,法线、UV和第一个切线几乎总是会被预先计算,除了非常严重的情况之外。特殊类型的几何。
请记住,Max、Maya 或 Blender 中模型的表示与运行时版本有很大不同。
编辑器软件
运行时间(对于DirectX,OpenGL,等)
通常,你会丢失很多无法重建的信息。如果您尽可能多地使用原始 Max/Maya 版本的几何体,您的艺术家将会感到最高兴。
Generally you'll want to precompute as much as possible. Most engines will have a custom written tool that can take in raw data from 3D software, and massage it into a format for run time (adding in tangents and bitangents, etc). However...
In certain situations the per-vertex memory overhead can be a particular performance concern. This is because there's an overhead associated with moving data about the system -- it's "hidden" because it's not an explicit as an instruction added into a shader, so it's a little more advanced.
In these cases, the bitangent may not be precomputed, and instead be constructed at runtime (in order to reduce the size of the vertex in memory). Bitangents are appropriate for this because they can be built from a normal, tangent and a directionality flag -- which are all properties of a single vertex.
Normals, some UV mappings and other things require knowledge of the "topology" of the mesh -- and this topology isn't usually present in runtime data. They also require extra markings from the artists; like sharp edges and textures seams, etc. For this reason, normals, UVs and the first tangent will almost always be precalculated for all but very specialised types of geometry.
Remember that that the representation of a model in Max, Maya or Blender is very different than the run time version.
Editor software
Run time (for DirectX, OpenGL, etc)
In general, you lose a lot of information that cannot be reconstructed. Your artists will be happiest if you do as much as you can with the original Max/Maya version of the geometry.
您还可以使用 D3D9 中的 ID3DXMesh 来完成此操作。您应该始终提前计算它们 - 因为在运行时再次计算它们是浪费的。但是,对于每个网格,您只能计算一次,因此除非您的程序按程序生成网格,否则在何时何地完成可能不是问题。
这里唯一重要的是在 CPU 上计算它们,而不是在 GPU 上,因为每一帧你都在 GPU 上一次又一次地执行这项工作,与在 CPU 上只执行一次相比,这完全是浪费。据我所知,所有 3D 渲染系统都会在 CPU 上计算一次法线等,将其保存到文件中,然后加载并将其发送到 GPU 进行工作。
You can also do this with ID3DXMesh in D3D9. You should always compute them in advance- because it's wasteful to compute them again at runtime. However, for each mesh, you'd only ever compute them once, so unless your program procedurally generates meshes, it's probably a non-issue about where and when it's done.
The only important thing here is to compute them on the CPU, not the GPU, because you're doing that work again and again on the GPU every frame, which is a total waste compared to just once on the CPU. As far as I know, all 3D rendering systems compute the normals and such on the CPU once, save it to the file, and then load it and send it off to the GPU for work.
我更喜欢预先计算它们,因为您需要对接缝、镜像纹理、环绕等进行特殊处理。
在运行时计算它并不完全是微不足道的,因为您可能需要比当前三角形数据更多的数据才能获得正确的切线空间。
I prefer to pre-compute them, as you need special handling with seams, mirrored textures, wraparounds and such.
It's not entirely trivial to compute it during runtime as you might need more than the current triangle data to get a correct tangent space.
UV 和法线通常由艺术家控制。可以使用 UV 的梯度来计算切线和副法线。一直计算切线和副法线往往有点昂贵,因此您通常会根据基础几何体预先计算它们一次。最好在发货前进行,以减少装载时间。
UVs and normals are usually under the control of the artist. Tangents and binormals can be calculated using the gradient of the UVs. It tends to be a bit expensive to calculate the tangent and binormals all the time, so you usually precalculate them based on the underlying geometry once. Preferably before you ship to reduce loading times.