在我深入研究将当前的渲染系统转换为openGL之前,这只是一个简单的问题。我听说纹理必须是基本2尺寸才能存储以便渲染。这是真的?
我的应用程序在内存上非常紧张,但大多数位图都不是2的幂。存储非基础2纹理会消耗更多内存吗?
答案 0 :(得分:10)
这取决于OpenGL ES版本,OpenGL ES 1.0 / 1.1具有两个限制的强大功能。 OpenGL ES 2.0没有这个限制,但是它限制了两种纹理的非幂的包裹模式。
创建更大的纹理以匹配POT尺寸会浪费纹理内存。
答案 1 :(得分:6)
GuyNoir,你应该做的是建立一个纹理图集。我上周末为自己的Android游戏解决了这个问题。我创建了一个名为TextureAtlas的类,它的构造函数调用glTexImage2D()来创建我选择的任何大小的大纹理(为像素值传递null)。然后我可以调用add(id,bitmap),它重复调用glTexSubImage2D()来打包更小的图像。 TextureAtlas类跟踪较大纹理中的已用空间和自由空间以及存储每个位图的矩形。然后渲染代码可以调用get(id)来获取图集中图像的矩形(然后它可以转换为纹理)坐标)。
旁注#1:选择打包各种纹理尺寸的最佳方法并非易事。我选择从TextureAtlas类中的简单逻辑开始(想想打字机+回车+换行)并确保以最佳顺序加载图像以利用该逻辑。在我的情况下,那是从最小的正方形图像开始,然后一直到中等方形图像。然后我加载任何短+宽图像,强制CR + LF,然后加载任何高+瘦图像。我最后加载了最大的square-ish图像。
侧注#2:如果您需要多个纹理图集,请尝试将每个图像内部的图像分组在一起,以最大限度地减少切换纹理所需的次数(这可能会导致性能下降)。例如,在我的Android游戏中,我将所有静态游戏板元素放入一个地图集中,并将所有各种动画效果的帧放在第二个地图集中。这样我就可以绑定地图集#1并在游戏板上绘制所有内容,然后我可以绑定地图集#2并在其上绘制所有特效。每帧两个纹理选择非常有效。
侧注3:如果你需要重复/镜像纹理,他们需要进入自己的纹理,你需要缩放它们(不要添加黑色像素来填充边缘)。
答案 2 :(得分:3)
不,它必须是2base。但是,您可以通过在图像的顶部和/或底部添加黑条来解决此问题,然后使用纹理坐标数组来限制纹理从图像中的映射位置。例如,假设您有一个13 x 16像素的纹理。您可以在右侧添加3个黑色像素,然后执行以下操作:
static const GLfloat texCoords[] = {
0.0, 0.0,
0.0, 13.0/16.0,
1.0, 0.0,
1.0, 13.0/16.0
};
现在,您有一个2base图像文件,但是非2base纹理。只需确保使用线性缩放:)
答案 3 :(得分:1)
这有点晚了但是OpenGL ES 1/2通过扩展支持2种纹理 的非功能。
主要是GL_OES_texture_npot。 iOS设备还有GL_IMG_texture_npot和GL_APPLE_texture_2D_limited_npot
通过调用glGetString(GL_EXTENSIONS)
并搜索所需的扩展程序来检查这些扩展程序。
我还建议保持纹理的大小为4的倍数,因为如果不是,一些硬件会拉伸纹理。