2017-04-21 43 views
0

我正在使用本机代码编写游戏,所有图形均使用OpenGL ES 2.0完成。我尝试通过反复创建并删除它们不需要的时候(使用glDeleteTextures)来节省纹理使用。我注意到,OpenGL将永远不会重复使用相同的纹理ID,在完成192个纹理创建之后,android屏幕会变成白色(首先是部分,下一次加载会使其完全),除非通过释放应用程序焦点并将其恢复,否则它不会恢复。这是一个错误还是功能? glFlush()也没有帮助。-SOLVED-在Android OpenGL ES 2.0中最大纹理创建/删除

我写了我自己的字体渲染引擎,它使用字体精灵图集将所有文本渲染为单独的新纹理。这样一来,实际的文本就完成了一次,随后的绘制调用仅用于一个纹理。但是,例如玩家姓名查询会在每次输入或删除一个新字母时重新创建文本纹理,在这里我很快遇到了192的限制。无论加载和删除哪些纹理都无关紧要,在创建一定数量的作品后,屏幕变白。

这种情况至少发生在我的Android设备上使用Android 6.0的三星J5 2016上运行。任何建议表示赞赏。

回答

1

找到原因。我实际上删除了framebuffer,并在每次创建纹理操作的新渲染时重新创建它。通过这样做创作只有一次

glGenFramebuffers(1, &m_renderFrameBuffer); 

,并在后续操作中重复使用它,并把删除

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

类的析构函数没碰上问题了。

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

1

在OpenGL和OpenGL ES中,纹理创建是一项昂贵的操作,因此建议您尽可能使用最小数量的纹理。你的字体渲染引擎使用纹理图集的方法是很好的。但是,如果您在游戏中持续使用Texture Atlas,则应该只在初始化过程中创建一次纹理。您只需在活动正在退出时销毁纹理对象,并且需要释放内存。因此,在运行时您只能使用Text Atlas使用的一个纹理。

OpenGL的一个有用的文本渲染库是FreeType。有一个example code here,它显示了初始化和在原生OpenGL应用程序中初始化和使用FreeType Texture Atlas所需的最低步骤(我已成功地将它与OpenGL ES Native Native应用程序集成在一起)。您可以使用类似的方法来制作自定义字体渲染引擎。

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

你可以在Android Activity Lifecycle here找到更多详细信息。这会给你一个关于初始化和破坏纹理的好主意。

+0

经过进一步的调查后,我发现这个问题与正常的纹理加载和卸载无关,而只与使用framebuffer渲染纹理有关。192也不是一个固定的数量,这是多次删除和创作的结果。真正的问题是,经过一定数量的渲染到纹理操作(通过适当的清理)之后,窗口变黑(首先部分,像馅饼,然后完全)。这使得我的文字渲染理念将所有字母渲染成新的纹理(无需分别在每一帧中绘制每一个字母)从长远来看不起作用? – kleimola

+0

很难确定是什么导致问题而不知道你是如何实现渲染调用的。你能提供一些示例代码吗?编辑 - 我刚刚看到你的文章与你想出的解决方案。 – sparkplug