5

我正在尝试为使用 OpenGL 制作的游戏绘制汽车。汽车对象存储在一个带有 .mtl 文件的 .obj 文件中。

这辆车有 500 多个顶点,100 多个面,需要使用我自己的顶点和片段着色器应用超过 50 种不同的纹理。我已经通过使用缓冲区对象来解决这个问题,它一次发送有关我的对象的所有信息。我的问题是尝试将不同的纹理应用于同一对象的不同表面。

我发现这个问题的答案是将纹理绑定到某个纹理编号(即 GL_TEXTURE0、GL_TEXTURE1 等...)并将 Sampler2D 传递给引用它的片段着色器。但是,我可以用这种方式存储超过 50 个纹理吗?据我所知,它转到 GL_TEXTURE32。

另外,我如何告诉着色器仅将纹理应用于汽车对象的某个面?

4

3 回答 3

10

您不能以这种方式渲染模型,您可以一次绑定所有纹理。一个片段着色器,即使对于高端的 GL 4.1 级硬件,也只能访问 16 个纹理。也就是说,它只能有 16 个采样器。

总纹理计数更高,因为其他着色器阶段也可以使用纹理。

处理它的正确方法是执行以下操作之一:

  1. 回到你的建模师那里,让他们减少模型的纹理数量。
  2. 使用工具构建纹理图集(即:将所有图像放入单个纹理中),适当更改模型的纹理坐标。根据您计划支持的硬件,这可以是大型 2D 纹理或 2D 纹理阵列。后者需要纹理坐标的第三个值:数组中图像的索引。
  3. 按纹理对三角形进行排序。对于每个纹理,渲染所有使用该纹理的三角形。

#3 是唯一不需要更改数据的解决方案。但请注意:如果您经常渲染这辆车(例如,每帧数千次),则状态更改开销可能是性能问题。#1 和#2 的某种组合是通常首选的方法。

顺便说一句,如果您的模型只有几百个面,但有50 个纹理,那么建模过程中可能出现了严重错误。

于 2011-07-22T10:13:10.360 回答
2

不可能像那样使用任意数量的纹理,而不是直接使用。

基本上有3种解决方案:

  • 使用更少的纹理
    • 将几个单独的纹理打包成一个图集。这需要您调整纹理坐标并注意创建 mipmap(尽管一个不错的工具会自动为您完成)。您可能还需要小心为各向异性过滤留出足够的边界。
    • 将多个单独的纹理打包到一个阵列纹理中。mipmap 和 aniso 没有问题,但需要硬件支持(GL 3.1 卡)
  • 拆分你的模型
    • 每辆车更多的绘制调用和更多的状态更改和管道停顿(对性能不利)
    • 解决方案:例如在一批中绘制所有车身,在一批中绘制所有轮胎,在另一批中绘制所有灯光以减少状态变化
  • 使用细节纹理和更少的“整体低细节”纹理
    • 类似于在地形上进行纹理处理的方式
    • 在像素着色器中组合,为每辆车提供单独的外观
于 2011-07-22T10:11:30.783 回答
0

为单个对象切换 50 个纹理将很快变成低性能的噩梦。使用纹理图集。

多重纹理旨在提供多个纹理层,如颜色层、凹凸层、光泽度等。但它们不能用于替换图集。

此外,如果您的模型由不同材料的部件组成,请将其拆分。每种材料都在自己的网格中。

于 2011-07-22T10:11:42.000 回答