Android OpenGL ES 2.0中最大的纹理创建/删除

时间:2017-04-21 13:10:49

标签: android android-ndk opengl-es-2.0

我正在用本机代码编写游戏,所有图形都是用OpenGL ES 2.0完成的。我已经尝试通过重复创建它们来保留纹理用法,并在不需要时删除(使用glDeleteTextures)。我注意到OpenGL永远不会重复使用相同的纹理ID,并且在完全192个纹理创建之后,android屏幕变为白色(首先是部分,下一次加载使其完全)并且它不会恢复,除非通过释放应用程序焦点并将其恢复。这是一个错误或功能吗? glFlush()也无济于事。

我编写了自己的字体渲染引擎,它使用字体精灵图集将所有文本渲染为单独的新纹理。这样,实际文本一次完成,后续绘制调用仅针对一个纹理。但是,例如每次输入或删除新字母时,播放器名称查询都会导致文本纹理重新创建,在这里我很快就遇到了192限制。加载和删除的纹理无关紧要,屏幕在固定数量的创建后变为白色。

至少在Android设备上使用Android 6.0运行Samsung J5 2016时会发生这种情况。任何建议都表示赞赏。

2 个答案:

答案 0 :(得分:1)

在OpenGL和OpenGL ES中,纹理创建是一项昂贵的操作,因此建议您尽可能使用最少数量的纹理。将纹理图集用于字体渲染引擎的方法很好。

但是,如果您在游戏中不断使用纹理图集,则只应在初始化期间创建一次纹理。您只需要在Activity退出时销毁纹理对象,并且需要释放内存。因此,在运行时期间,只有一个纹理用于​​文本图集。

OpenGL的一个有用的文本呈现库是FreeType。有一个example code here显示了在本机OpenGL应用程序中初始化和使用FreeType纹理图集所需的最小步骤(我已成功将其与我的OpenGL ES Native Android应用程序集成)。您可以对自定义字体呈现引擎采用类似的方法。

对于原生Android应用程序,您可以通过JNI绑定到onSurfaceCreated回调中的本机初始化方法来调用本机OpenGL ES代码的初始化。应该通过JNI从onDestroy回调来调用破坏纹理并释放本机代码中的内存。

您可以在Android Activity Lifecycle here找到更多详细信息。这将使您了解初始化和销毁​​纹理的位置。

答案 1 :(得分:1)

找出原因。我实际上是在每次创建一个新的渲染到纹理操作时删除帧缓冲并重新创建它。通过仅创建一次

glGenFramebuffers(1, &m_renderFrameBuffer);

并在后续操作中重复使用并放置删除

if (m_renderFrameBuffer != 0)
{
    glDeleteFramebuffers(1, &m_renderFrameBuffer);
    m_renderFrameBuffer = 0;
}

到类析构函数我不再遇到问题了。

但是在众多的例子中这并不明显,或者至少没有警告过。似乎做很多帧缓冲创建和删除最终会耗尽一些资源。