2010-03-23 41 views
6

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

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

我的第二个问题是加载纹理时,我必须根据我的游戏数据来推断要加载的纹理。这意味着我会玩弄字符串,我明白这是我在GL线程中不应该做的事情。

总体而言,我了解加载纹理时发生了什么,我只想从中获得最好的生命周期。还有什么我应该考虑的事情吗?

回答

14

1)您应该根据需要分配尽可能多的纹理名称。一个用于你正在使用的每个纹理。

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

请注意,在您不再需要纹理之后,您必须使用glDeleteTextures将其删除。 2)如果你的意思是推断你需要不同的纹理或不同的层次或类似的东西,那么你应该在加载状态下处理关卡数据并决定需要加载哪些纹理。另一方面,如果您需要绘制文本(如当前分数),那么OpenGL中的事情会变得更加复杂。您将有以下选择:将所需文本预渲染到纹理(简单),实现自己的位图字体引擎(较难)或使用位图和画布对快速生成纹理(较慢)。

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

对于当前分数,只需具有一个纹理,该纹理的数字从0到9的字形,并使用该纹理来渲染任意值。实现将非常简单。

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

3)关于纹理和获得最好的GPU,你至少应该在脑海中保留下面的东西(这些东西会更先进一些,只有在你获得应用程序后,你才应该打扰他们如果您需要优化帧率):

  • 最小化纹理更改,因为它是一个缓慢的操作。理想情况下,您应该使用同一个纹理批量渲染所有对象。然后改变纹理并渲染需要的对象 等等。
  • 使用纹理图集来最小化纹理的数量(和纹理更改)
  • 如果您有很多纹理,则可能需要使用比8888更多的位深度才能使所有纹理适合内存。使用较低的位深度也可以提高性能。
+2

当你说“加载状态”时,是否可以在初始化我的渲染器的同时正常运行? 我目前的想法是让它初始化我的场景图并查询场景图中的所有对象,以获得最终要求的纹理(通过让它们从游戏模型中推断出名称)。 然后,每个请求纹理的对象都将被提供相应的OpenGL整数“名称”的纹理它要求。 这听起来好听吗? – 2010-03-24 19:57:27

+2

我喜欢使用状态机为高级应用程序逻辑建模。因此术语加载状态。 在完成初始化的其余部分的同时完成此操作是完全正确的。这只是你想如何设计你的应用程序逻辑的问题。 所以它看起来很合理。 – Lauri 2010-03-25 06:35:16

2

这应该是对劳里的回答评论,但我不能与1名代表发表意见,而且也应该指出的一件事:

您应该重新加载纹理每次您EGL上下文丢失(即,当你的应用程序被放置到后台并返回时)。所以,(重新)加载它们的正确位置在于渲染器的方法

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

。显然,如果你有不同的纹理集要根据你正在玩的游戏级别进行加载,那么当你改变级别时,你应该删除你不打算使用的纹理并加载新的纹理。另外,您必须跟踪在EGL上下文丢失时必须重新加载的内容。