OpenGL - 同一对象的不同表面上的不同纹理

时间:2011-07-22 09:57:07

标签: opengl textures texturing

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

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

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

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

3 个答案:

答案 0 :(得分:8)

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

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

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

  1. 返回建模器并让它们减少模型的纹理数量。
  2. 让工具构建纹理图集(即:将所有图像放入单个纹理中),适当地更改模型的纹理坐标。根据您计划支持的硬件,这可以是大型2D纹理或2D纹理阵列。后者将需要纹理坐标的第3个值:数组中图像的索引。
  3. 按纹理对三角形进行排序。对于每个纹理,渲染使用该纹理的所有三角形。
  4. #3是唯一不需要更改数据的解决方案。但要注意:如果你经常渲染这款车(比如每帧数千次),状态变化开销可能是性能问题。 #1和#2的某种组合是通常优选的方法。

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

答案 1 :(得分:1)

不可能像这样使用任意数量的纹理,而不是以直截了当的方式。

基本上有3种解决方案:

  • 使用较少的纹理
    • 将几个单独的纹理打包到地图集中。这需要你 调整纹理坐标并注意创建mipmap (虽然一个不错的工具会自动为你做这件事)。您可能需要小心为各向异性过滤留下足够的边框。
    • 将多个单独的纹理打包到一个数组纹理中。没有mipmaps和aniso的问题,但需要硬件支持(GL 3.1卡)
  • 拆分模型
    • 更多绘制调用和更多状态更改以及每辆车的 管道停滞(性能不佳)
    • 解决方案:绘制例如所有车体在一批中,所有轮胎在一批中,所有车灯在另一批中以减少状态变化
  • 使用细节纹理和更少的“整体低细节”纹理
    • 类似于在地形上进行纹理处理
    • 在像素着色器中组合以为每辆车提供单独的外观

答案 2 :(得分:0)

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

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

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