线程纹理加载进程为android opengl游戏

Vic*_*tor 9 android textures opengl-es

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

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

我无法解压缩所有纹理,然后在onSurfaceCreated(...)中将它们加载到opnegl中,因为它们可能不适合有限的vm内存(20-40MB?)

这意味着我必须逐个解压缩并加载它们,但在这种情况下我无法得到一个opengl指针.

有人,请给我和opengl游戏纹理加载的例子?

它必须是一些典型的程序,我无法在任何地方获得任何信息.

Rod*_*dja 10

正如' OpenGLES在其他线程中预加载纹理 '中所解释的那样,有两个独立的步骤:位图创建和位图上传.在大多数情况下,只需在辅助线程上创建位图就可以了 - 这非常简单.

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

EGLContext textureContext = egl.eglCreateContext(display, eglConfig, renderContext, null);
Run Code Online (Sandbox Code Playgroud)

获取参数eglCreateContext有点棘手.你需要使用setEGLContextFactorySurfaceView的钩子进入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;
}
Run Code Online (Sandbox Code Playgroud)

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

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
}
Run Code Online (Sandbox Code Playgroud)

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

该解决方案基于互联网上的许多来源.最有影响力的三个:


Chr*_*ica 2

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