【问题标题】:Loading textures in an Android OpenGL ES App在 Android OpenGL ES 应用程序中加载纹理
【发布时间】:2010-03-23 15:36:41
【问题描述】:

我想知道是否有人可以建议在 Android Java 和 OpenGL ES 应用程序中加载纹理的好模式。

我首先关心的是确定要分配多少纹理名称以及如何在渲染顶点之前有效地执行此操作。

我的第二个问题是加载纹理,我必须根据我的游戏数据推断要加载的纹理。这意味着我将玩弦乐,我知道这是我真的不应该在我的 GL 线程中做的事情。

总的来说,我了解加载纹理时会发生什么,我只是想从中获得最佳生命周期。还有什么我应该考虑的吗?

【问题讨论】:

    标签: java android opengl-es textures


    【解决方案1】:

    1) 您应该根据需要分配尽可能多的纹理名称。您使用的每种纹理都有一个。

    加载纹理是一项非常繁重的操作,它会停止渲染管道。所以,你永远不应该在你的游戏循环中加载纹理。您应该在渲染纹理的应用程序状态之前有一个加载状态。加载状态负责加载渲染中需要的所有纹理。因此,当您需要渲染几何图形时,您将加载所有纹理,您不必再担心了。

    请注意,当您不再需要纹理后,您必须使用 glDeleteTextures 删除它们。

    2) 如果您的意思是推断不同关卡需要不同的纹理或类似的东西,那么您应该在加载状态下处理关卡数据并决定需要加载哪些纹理。

    另一方面,如果您需要绘制文本(如当前乐谱),那么 OpenGL 中的事情会变得更加复杂。您将有以下选择:将所需的文本预渲染到纹理(简单)、实现自己的位图字体引擎(更难)或使用位图和画布对动态生成纹理(慢)。

    如果您在游戏中显示的消息集有限,那么我很可能会将它们预渲染到纹理中,因为实现非常简单。

    对于当前的分数,拥有一个具有 0 到 9 数字字形的纹理并使用它来渲染任意值就足够了。实现将非常简单。

    如果您需要更长的本地化文本,那么您需要开始考虑动态生成纹理。基本上,您将创建一个位图,使用 Canvas 在其中呈现文本。然后您将其作为纹理上传并将其渲染为任何其他纹理。在你不再需要它之后,你会删除它。此选项速度较慢,应避免在应用程序循环中使用。

    3) 关于纹理和充分利用 GPU,您至少应该记住以下几点(这些事情会变得更高级,只有在启动应用程序后才应该考虑它们并运行,如果您需要优化帧速率):

    • 尽量减少纹理更改,因为这是一个缓慢的操作。最佳情况下,您应该批量使用相同的纹理渲染所有对象。然后更改纹理并渲染对象 需要那个等等。
    • 使用纹理图集最大限度地减少纹理(和纹理更改)的数量
    • 如果您有很多纹理,您可能需要使用 8888 以外的其他位深度来使所有纹理适合内存。使用较低的位深度也可以提高性能。

    【讨论】:

    • 当您说“加载状态”时,可以在初始化渲染器的同时进行吗?我目前的想法是让它初始化我的场景图并查询场景图中的所有对象以获取它们最终会请求的纹理(通过让它们从游戏模型中推断名称)。然后,每个请求纹理的对象都将被提供它所请求的纹理的相应 OpenGL 整数“名称”。这听起来不错?
    • 我喜欢使用状态机对高级应用程序逻辑进行建模。因此术语加载状态。在进行其余初始化的同时执行此操作是完全可以的。这只是您希望如何设计应用程序逻辑的问题。所以看起来确实不错。
    【解决方案2】:

    这应该是对劳里的回答的评论,但我不能用 1 个代表发表评论,有一点需要指出:

    您应该每次重新加载纹理,您的 EGL 上下文丢失(即当您的应用程序被置于后台并再次返回时)。因此,(重新)加载它们的正确位置在方法中

    public void onSurfaceChanged(GL10 gl, int width, int height)
    

    的渲染器。显然,如果您要基于(即)您正在玩的游戏级别加载不同的纹理集,那么当您更改级别时,您应该删除您不打算使用的纹理并加载新纹理。此外,您必须跟踪丢失 EGL 上下文时必须重新加载的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-16
      • 2012-04-08
      相关资源
      最近更新 更多