我正在尝试在OpenGL ES 2.0中为Android游戏制作一张2D地图(用于游戏,想想平铺世界地图)。基本上,有一些具有不同纹理的图块类型,并且地图是从这些类型中随机生成的,因此从游戏到游戏,地图会发生变化,但在单个游戏的持续时间内它会保持不变。
我的第一个想法是先生成一个大的纹理/图像/位图(独立于OpenGL),基本上将复制的瓷砖纹理拼接在一起以制作更大的地图,然后将这个单一纹理用于一个大的地图矩形。从理论上讲,我认为这很简单并且可以正常工作,但是我担心它对于较大的地图不会很好地扩展,特别是在移动设备上我会用这么大的图像映射耗尽内存。另外,还有一小部分瓷块一遍又一遍地重复,因此在一次又一次地复制大纹理中的像素数据似乎是一种巨大的浪费。
我的第二个想法是拥有许多纹理,每个纹理纹理一个。但我不确定这是如何工作的,纹理绑定方面,我是否需要着色器包含多个纹理参考,并且着色器中有使用正确的逻辑?
最后,我认为使用纹理图集可以工作,有一个纹理/图像包含其中的所有图块数据,这将相对较小。但我正在努力想象如何让数学计算出来,使得地图矩形的“平铺”或子部分将使用完全不同的纹理坐标。
我接近这个错误的方式吗?我应该为每个瓷砖使用矩形吗?至少这样我可以独立地为每个图块传递着色器顶点和纹理坐标。这似乎更容易,但似乎也错了,因为地图实际上只是一个不会改变的矩形。
答案 0 :(得分:0)
我的第一个想法是生成一个大的纹理......
我的第二个念头是有很多纹理......
您不需要在着色器中保存所有纹理。这样做:
实现一个包含n次迭代的循环,其中n是使用了多少种不同类型的纹理。
在循环内部,绑定当前纹理类型。
将任何数据(如位置/颜色/纹理坐标)传递给着色器。
绘制使用有界纹理的所有图块。如果您使用GLES 3.x或适当的扩展程序支持定位设备,则可以使用GLES30.glDrawElementsInstanced
或GLES30.glDrawArraysInstanced
。否则,请使用GLES20.glDrawArrays
或GLES20.glDrawElements
绘制切片。
着色器不会因这种方法而变得复杂。
最后,我认为使用纹理图集可以起作用......
考虑到您的地图在游戏会话中没有变化,MegaTexture方法看起来很不错。但是,这取决于地图的大小和可用的内存量。另请注意,最大纹理大小是有限的。最大尺寸因设备而异,但应该是(AFAIK)等于或大于屏幕尺寸和至少64个纹素(16个用于立方体贴图纹理)。您可以使用glGet(GL_MAX_TEXTURE_SIZE )
在任何设备上获得最大纹理大小。