简体   繁体   English

OpenGL - 同一 object 的不同表面上的不同纹理

[英]OpenGL - Different textures on different surfaces of the same object

I'm trying to draw a car for a game I'm making using OpenGL.我正在尝试为我正在使用 OpenGL 制作的游戏绘制汽车。 The car object is stored in an.obj file with an accompanying.mtl file.汽车 object 存储在一个带有随附.mtl 文件的 .obj 文件中。

The car has 500+ vertices, 100+ faces and needs over 50 different textures applied to them, using my own vertex and fragment shader.这辆车有 500 多个顶点,100 多个面,需要使用我自己的顶点和片段着色器应用超过 50 种不同的纹理。 I've gone about this by using buffer objects, which sends all information about my object at once.我已经通过使用缓冲区对象解决了这个问题,它一次发送有关我的 object 的所有信息。 My problem is trying to apply different textures to different surfaces of the same object.我的问题是尝试将不同的纹理应用于同一 object 的不同表面。

The answers I've found to this problem are to bind a texture to a certain texture number (ie GL_TEXTURE0, GL_TEXTURE1, etc...) and pass in a Sampler2D to the fragment shader referencing it.我发现这个问题的答案是将纹理绑定到某个纹理编号(即 GL_TEXTURE0、GL_TEXTURE1 等...)并将 Sampler2D 传递给引用它的片段着色器。 However, can I store over 50 textures in this way?但是,我可以用这种方式存储超过 50 个纹理吗? As far as I can tell it goes to GL_TEXTURE32.据我所知,它转到 GL_TEXTURE32。

Also, how would I tell the shader to only apply a texture to a certain face of the car object?另外,我如何告诉着色器仅将纹理应用于汽车 object 的某个面?

You cannot render the model this way, where you bind all the textures at once.您不能以这种方式渲染 model,您可以一次绑定所有纹理。 A fragment shader, even for high-end GL 4.1-class hardware, can only access 16 textures.一个片段着色器,即使对于高端的 GL 4.1 级硬件,也只能访问 16 个纹理。 That is, it can only have 16 samplers.也就是说,它只能有 16 个采样器。

The total texture count is higher because other shader stages can use textures as well.总纹理计数更高,因为其他着色器阶段也可以使用纹理。

The correct way to deal with it is to do one of the following:处理它的正确方法是执行以下操作之一:

  1. Return to your modeller and have them reduce the texture count of the model.返回到您的建模器并让他们减少 model 的纹理计数。
  2. Have a tool build a texture atlas (ie: put all of the images into a single texture), changing the model's texture coordinates appropriately.使用工具构建纹理图集(即:将所有图像放入单个纹理中),适当更改模型的纹理坐标。 Depending on the hardware you plan to support, this can be a large 2D texture or a 2D texture array.根据您计划支持的硬件,这可以是大型 2D 纹理或 2D 纹理阵列。 The latter will require a 3rd value for the texture coordinate: the index of the image in the array.后者需要纹理坐标的第三个值:数组中图像的索引。
  3. Sort the triangles by texture.按纹理对三角形进行排序。 For each texture, render all of the triangles that use that texture.对于每个纹理,渲染所有使用该纹理的三角形。

#3 is the only solution that doesn't require changing data. #3 是唯一不需要更改数据的解决方案。 But be warned: if you render this car often (say, thousands of times per frame) the state change overhead can be a performance issue.但请注意:如果您经常渲染这辆车(例如,每帧数千次),则 state 更改开销可能是性能问题。 Some combination of #1 and #2 is the generally preferred method. #1 和#2 的某种组合是通常首选的方法。

BTW, if your model only has a few hundred faces, but 50 textures, then it's likely something went horribly wrong in the modelling process.顺便说一句,如果您的 model 只有几百个面,但有50 个纹理,那么建模过程中可能出现了严重错误。

It's not possible to use an arbitrary number of textures just like that, not in a straightforward way.不可能像那样使用任意数量的纹理,而不是直接使用。

There are basically 3 solutions:基本上有3种解决方案:

  • Use fewer textures使用更少的纹理
    • Pack several individual textures into an atlas.将几个单独的纹理打包成一个图集。 This requires you to adjust texture coordinates and take care at mipmap creation (though a decent tool will do that for you automatically).这需要您调整纹理坐标并注意创建 mipmap(尽管一个不错的工具会自动为您完成)。 You may need to be careful to leave a sufficient border for anisotropic filtering too.您可能还需要小心为各向异性过滤留出足够的边界。
    • Pack several individual textures into one array texture.将多个单独的纹理打包到一个阵列纹理中。 No problems with mipmaps and aniso, but needs hardware support (GL 3.1 cards) mipmap 和 aniso 没有问题,但需要硬件支持(GL 3.1 卡)
  • Split up your model拆分你的 model
    • More draw calls and many more state changes and pipeline stalls per car (bad for performance)更多的绘制调用和更多的state 更改和每辆车的管道停顿(对性能不利)
    • Solution: Draw eg all car bodies in one batch, all tires in one batch, and all lights in another to reduce state changes解决方案:例如绘制一批所有车身,一批绘制所有轮胎,另一批绘制所有灯,以减少 state 变化
  • Use detail texturing and fewer "overall low detail" textures使用细节纹理和更少的“整体低细节”纹理
    • similar to how you do texturing on a terrain类似于在地形上进行纹理处理的方式
    • combine in the pixel shader to give each car an individual appearance在像素着色器中组合,为每辆车提供单独的外观

Switching 50 textures for a single object will quickly turn into a low-performance nightmare.为单个 object 切换 50 个纹理将很快变成低性能的噩梦。 Use a texture atlas.使用纹理图集。

Multitexturing is meant to provide multiple texture layers, like a colour layer, a bump layer, shinyness, etc. But they are not to be used for replacement of an atlas.多重纹理旨在提供多个纹理层,如颜色层、凹凸层、光泽度等。但它们不能用于替换图集。

Also if your model consists of parts with different material, split it up.此外,如果您的 model 由不同材料的部件组成,请将其拆分。 Each material in its own mesh.每种材料都在自己的网格中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM