简体   繁体   English

在Android OpenGL ES App中加载纹理

[英]Loading textures in an Android OpenGL ES App

I was wondering if anyone could advise on a good pattern for loading textures in an Android Java & OpenGL ES app. 我想知道是否有人可以建议在Android Java和OpenGL ES应用程序中加载纹理的良好模式。

My first concern is determining how many texture names to allocate and how I can efficiently go about doing this prior to rendering my vertices. 我首先关心的是确定要分配多少纹理名称以及如何在渲染顶点之前有效地执行此操作。

My second concern is in loading the textures, I have to infer the texture to be loaded based on my game data. 我的第二个问题是加载纹理,我必须根据我的游戏数据推断要加载的纹理。 This means I'll be playing around with strings, which I understand is something I really shouldn't be doing in my GL thread. 这意味着我将使用字符串,我理解这是我在GL线程中不应该做的事情。

Overall I understand what's happening when loading textures, I just want to get the best lifecycle out of it. 总的来说,我了解加载纹理时发生了什么,我只是希望从中获得最佳生命周期。 Are there any other things I should be considering? 还有其他我应该考虑的事情吗?

1) You should allocate as many texture names as you need. 1)您应该根据需要分配尽可能多的纹理名称。 One for each texture you are using. 一个用于您正在使用的每个纹理。

Loading a texture is a very heavy operation that stalls the rendering pipeline. 加载纹理是一项非常繁重的操作,会使渲染管道停顿。 So, you should never load textures inside your game loop. 所以,你永远不应该在游戏循环中加载纹理。 You should have a loading state before the application state in which you render the textures. 您应该在呈现纹理的应用程序状态之前具有加载状态。 The loading state is responsible for loading all the textures needed in the rendering. 加载状态负责加载渲染中所需的所有纹理。 So when you need to render your geometry, you will have all the textures loaded and you don't have to worry about that anymore. 因此,当您需要渲染几何体时,您将加载所有纹理,您不必再担心它了。

Note that after you don't need the textures anymore, you have to delete them using glDeleteTextures. 请注意,在不再需要纹理之后,必须使用glDeleteTextures删除它们。

2) If you mean by infer that you need different textures for different levels or something similar, then you should process the level data in the loading state and decide which textures need to be loaded. 2)如果你的意思是通过推断你需要不同级别或类似的不同纹理,那么你应该处理加载状态的级别数据并决定需要加载哪些纹理。

On the other hand, if you need to paint text (like current score), then things get more complicated in OpenGL. 另一方面,如果你需要绘制文本(比如当前得分),那么在OpenGL中事情变得更加复杂。 You will have the following options: prerender the needed text to textures (easy), implement your own bitmap font engine (harder) or use Bitmap and Canvas pair to generate textures on the fly (slow). 您将有以下选项:将所需文本预渲染到纹理(简单),实现您自己的位图字体引擎(更难)或使用Bitmap和Canvas对动态生成纹理(慢)。

If you have limited set of messages to be shown during the game, then I would most probably prerender them to textures as the implementation is pretty trivial. 如果你在游戏中显示有限的消息集,那么我很可能会将它们预渲染到纹理,因为实现非常简单。

For the current score it is enough to have a texture which has a glyph for numbers from 0 to 9 and to use that to render arbitrary values. 对于当前分数,足以具有纹理,该纹理具有0到9的数字的字形并且用于呈现任意值。 The implementation will be quite straightforward. 实施将非常简单。

If you need longer localized texts then you need to start thinking about the generating textures on the fly. 如果您需要更长的本地化文本,那么您需要开始考虑动态生成纹理。 Basically you would create an bitmap into which you render text using a Canvas. 基本上,您将创建一个使用Canvas渲染文本的位图。 Then you would upload it as a texture and render it as any other texture. 然后,您将其作为纹理上传并将其渲染为任何其他纹理。 After you don't need it any more, then you would delete it. 在您不再需要它之后,您将删除它。 This option is slow and should be avoided inside the application loop. 此选项很慢,应该在应用程序循环中避免。

3) Concerning textures and to get the best out of the GPU you should keep at least the following things in your mind (these things will get a bit more advanced, and you should bother with them only after you get the application up and running and if you need to optimize the frame rate): 3)关于纹理并从GPU中获得最佳效果,你应该至少记住下面的事情(这些事情会变得更先进,只有在你启动并运行应用程序后才能使用它们。如果你需要优化帧率):

  • Minimize texture changes as it is a slow operation. 最小化纹理更改,因为它是一个缓慢的操作。 Optimally you should render all the objects using the same texture in a batch. 最理想的是,您应该批量使用相同的纹理渲染所有对象。 Then change the texture and render the objects needing that and so on. 然后更改纹理并渲染需要它的对象,依此类推。
  • Use texture atlases to minimize the number of textures (and texture changes) 使用纹理图集来最小化纹理数量(和纹理更改)
  • If you have lots of textures, you could need to use other bit depths than 8888 to make all your textures to fit in to the memory. 如果你有很多纹理,你可能需要使用8888以外的其他位深度来使所有纹理适合内存。 Using lower bit depths may also improve performance. 使用较低的位深度也可以提高性能。

This should be a comment to Lauri's answer, but i can't comment with 1 rep, and there's a thing that should be pointed out: 这应该是对Lauri的答案的评论,但我不能用1代表评论,并且有一件事应该指出:

You should re-load textures every time your EGL context is lost (ie when your applications is put to background and back again). 每当您的EGL上下文丢失时(即当您的应用程序被置于后台并再次返回时),您应该重新加载纹理。 So, the correct location to (re)load them is in the method 因此,(重新)加载它们的正确位置在方法中

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

of the renderer. 渲染器。 Obviously, if you have different textures sets to be loaded based (ie) on the game level you're playing then when you change level you should delete the textures you're not going to use and load the new textures. 显然,如果你有不同的纹理集要加载(即)你正在玩的游戏级别,那么当你改变等级时你应该删除你不会使用的纹理并加载新的纹理。 Also, you have to keep track of what you have to re-load when the EGL context is lost. 此外,您必须跟踪EGL上下文丢失时必须重新加载的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM