【问题标题】:How to texture a rectangle with multiple textures in OpenGL如何在OpenGL中对具有多个纹理的矩形进行纹理化
【发布时间】:2026-02-09 23:15:02
【问题描述】:

我正在尝试在 OpenGL ES 2.0 中为 android 游戏制作 2d 地图(对于游戏,想想平铺的世界地图)。基本上,有几种瓷砖类型具有不同的纹理,并且地图是从这些类型中随机生成的,因此从游戏到游戏地图会发生变化,但在单个游戏的持续时间内它保持不变。

我的第一个想法是预先生成一个大纹理/图像/位图(独立于 OpenGL),基本上将重复的平铺纹理拼接在一起以制作更大的地图,然后将这个单一纹理用于一个大地图矩形。从理论上讲,我认为这很简单并且可以正常工作,但我担心它不能很好地适用于较大的地图,尤其是在移动设备上,我会用如此大的图像地图耗尽内存。另外,有一小部分瓷砖会反复复制,因此在大纹理中反复复制像素数据似乎是一种巨大的浪费。

我的第二个想法是有很多纹理,每个瓷砖纹理都有一个。但是我不确定这将如何工作,纹理绑定,我是否需要着色器包含多个纹理引用,并且在着色器中有使用正确的逻辑?

最后,我认为使用纹理图集可以工作,拥有一个包含所有平铺数据的纹理/图像,这将相对较小。但是我很难想象如何进行数学运算,以使地图矩形的“图块”或子部分使用完全不同的纹理坐标。

我是不是以错误的方式处理这个问题?我应该为每个瓷砖使用一个矩形吗?至少通过这种方式,我可以独立地为每个图块传递着色器的顶点坐标和纹理坐标。这似乎更容易,但也似乎是错误的,因为地图实际上只是一个不会改变的矩形。

【问题讨论】:

    标签: android opengl-es


    【解决方案1】:

    我的第一个想法是生成单个大纹理...

    • 实际上,id Software 的 id Tech 从版本 4 开始就已经使用了类似的东西。它被称为 MegaTexture。基本上,它是一个大纹理,还可以保存额外的数据。

    我的第二个想法是有很多纹理......

    • 您不需要将所有纹理保存在着色器中。这样做:

      1. 实现具有 n 次迭代的循环,其中 n 是使用了多少不同类型的纹理。

      2. 在循环中,绑定当前纹理类型。

      3. 将任何数据(例如位置/颜色/纹理坐标)传递给着色器。

      4. 绘制所有使用有界纹理的图块。如果您的目标设备具有 GLES 3.x 或适当的扩展支持,您可以使用 GLES30.glDrawElementsInstancedGLES30.glDrawArraysInstanced。否则,使用GLES20.glDrawArraysGLES20.glDrawElements 绘制您的图块。

      这种方法不会使着色器变得复杂。

    最后,我认为使用纹理图集可以工作......

    • 您也可以在此处使用循环并计算 CPU 上每种图块类型的纹理坐标,然后将它们传递给着色器。

    考虑到您的地图不会在游戏会话中发生变化,MegaTexture 方法看起来不错。但是,这取决于您的地图有多大以及有多少可用内存。另外,请注意最大纹理大小是有限的。最大尺寸因设备而异,但应(AFAIK)等于或大于屏幕尺寸和至少 64 纹素(立方体贴图纹理为 16)。您可以使用 glGet(GL_MAX_TEXTURE_SIZE ) 在任何设备上获取最大纹理大小。

    【讨论】: