我有大量 JPG 格式的纹理。 我需要在实际绘图开始之前将它们预加载到 opengl 内存中。 我问了一个问题,有人告诉我这样做的方法是将 JPEG 解包与对另一个线程的 glTexImage2D(...) 调用分开。 问题是我不太确定该怎么做。
执行 glTexImage2D 所需的 OpenGL(处理程序?)仅在 GLSurfaceView.Renderer 的 onSurfaceCreated 和 OnDrawFrame 方法中可用。
我无法解压我所有的纹理,然后在 onSurfaceCreated(...) 中将它们加载到 opnegl 中, 因为它们可能不适合有限的虚拟机内存(20-40MB?)
这意味着我必须一个接一个地解压和加载它们,但在那种情况下我无法获得 opengl 指针。
有人可以给我和 opengl 游戏的纹理加载线程示例吗?
这一定是一些典型的程序,我无法在任何地方获得任何信息。
最佳答案
如“OpenGLES preloading textures in other thread”中所述' 有两个独立的步骤:位图创建和位图上传。在大多数情况下,您只需在辅助线程上创建位图就可以了——这相当简单。
如果您在上传纹理时遇到帧丢失的情况,请从后台线程调用texImage2D
。为此,您需要创建一个新的 OpenGL 上下文,它与您的渲染线程共享它的纹理,因为每个线程都需要它自己的 OpenGL 上下文。
EGLContext textureContext = egl.eglCreateContext(display, eglConfig, renderContext, null);
获取 eglCreateContext
的参数有点棘手。您需要在 SurfaceView
上使用 setEGLContextFactory
来 Hook EGLContext 创建:
@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 创建了上述代码 fragment 的工作演示.
此解决方案基于互联网上的许多资源。这三个最有影响力的地方:
关于android - android opengl游戏的线程纹理加载过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6318311/