线程纹理加载android opengl游戏的过程

我有大量的JPG格式的纹理。 我需要在实际绘图开始之前将它们预加载到opengl内存中。 我问过一个问题,我已经被告知要做到这一点的方法是将JPEG解包和glTexImage2D(…)调用分开到另一个线程。 问题是我不太清楚如何做到这一点。

执行glTexImage2D所需的OpenGL(处理程序?)仅在GLSurfaceView.Renderer的onSurfaceCreated和OnDrawFrame方法中可用。

我不能解压所有我的纹理,然后在onSurfaceCreated(…)加载它们在opnegl,因为他们可能不适合有限的VM内存(20-40MB?)

这意味着我必须解压并逐个加载它们,但是在这种情况下,我不能得到一个opengl指针。

请问有人可以给我和opengl游戏的纹理加载线程的例子吗?

这一定是一些典型的程序,我不能在任何地方得到任何信息。

Solutions Collecting From Web of "线程纹理加载android opengl游戏的过程"

你只需要上传例程的主线程,它可以访问OpenGL并调用glTexImage2D。 另一个线程将图像从文件加载(解码)到内存。 当辅助线程加载下一个图像时,主线程将先前加载的图像上载到纹理中。 所以你只需要两个图像的内存,一个是当前从文件加载的图像,另一个是上载到GL(这是之前加载的图像)的图像。 当然,你需要一些同步,以防止加载器线程覆盖内存,主线程当前发送给GL,并防止主线程发送未完成的数据。

正如在“ OpenGLES预加载其他线程中的纹理”中所解释的,有两个单独的步骤:位图创build和位图上传。 在大多数情况下,只需在辅助线程上创build位图即可,这很容易。

如果您在上传纹理时遇到了帧丢失 ,请从后台线程调用texImage2D 。 要做到这一点,你需要创build一个新的OpenGL上下文,它与你的渲染线程共享纹理,因为每个线程都需要它自己的OpenGL上下文。

 EGLContext textureContext = egl.eglCreateContext(display, eglConfig, renderContext, null); 

获取eglCreateContext的参数有点棘手。 你需要在你的SurfaceView上使用setEGLContextFactory来创buildEGLContext:

 @Override public EGLContext createContext(final EGL10 egl, final EGLDisplay display, final EGLConfig eglConfig) { EGLContext renderContext = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, null); // create your texture context here return renderContext; } 

然后你准备开始一个纹理加载线程:

 public void run() { int pbufferAttribs[] = { EGL10.EGL_WIDTH, 1, EGL10.EGL_HEIGHT, 1, EGL14.EGL_TEXTURE_TARGET, EGL14.EGL_NO_TEXTURE, EGL14.EGL_TEXTURE_FORMAT, EGL14.EGL_NO_TEXTURE, EGL10.EGL_NONE }; EGLSurface localSurface = egl.eglCreatePbufferSurface(display, eglConfig, pbufferAttribs); egl.eglMakeCurrent(display, localSurface, localSurface, textureContext); int textureId = loadTexture(R.drawable.waterfalls); // here you can pass the textureId to your // render thread to be used with glBindTexture } 

我在https://github.com/perpetual-mobile/SharedGLContextsTest上创build了上述代码片段的工作演示。

这个解决scheme基于互联网上的许多来源。 这三个影响最大的是:

“在初始化函数之外,必须有一种方法来调用GL函数。” – 是的。 只需将指针复制到gl并在任何地方使用。

“只要确保只在主线程中使用OpenGL”。 很重要。 您不能在您的游戏引擎(可能在另一个线程中)调用与gl线程不同步的纹理加载函数。 设置一个标志来指示你的gl线程加载一个新的纹理(例如,你可以在OnDrawFrame(GL gl)中放置一个函数来检查是否必须加载一个新的纹理。

find一个解决scheme,这实际上很容易:加载位图(在一个单独的线程)后,将其存储在一个实例variables,并在draw方法,你检查是否被初始化,如果是,加载纹理。 像这样的东西:

 if (bitmap != null && textureId == -1) { initTexture(gl, bitmap); } 

要添加到Rodja的答案 ,如果你想要一个OpenGL ES 2.0上下文,然后使用以下来创build上下文:

 final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; int[] contextAttributes = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; EGLContext renderContext = egl.eglCreateContext( display, config, EGL10.EGL_NO_CONTEXT, contextAttributes); 

您还需要调用setEGLContextClientVersion(2) ,因为这也是由默认configurationselect器使用的。

这是基于eglCreateContext中的属性列表