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有点棘手.你需要使用setEGLContextFactory你SurfaceView的钩子进入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上创建了上述代码片段的工作演示.
该解决方案基于互联网上的许多来源.最有影响力的三个:
您只需拥有带有上传例程的主线程,该例程可以访问 OpenGL 并调用 glTexImage2D。另一个线程将图像从文件加载(并解码)到内存。当辅助线程加载下一个图像时,主线程将先前加载的图像上传到纹理中。因此,您只需要存储两张图像的内存,一张当前从文件加载,一张当前上传到 GL(这是之前加载的一张)。当然,您需要一些同步,以防止加载线程覆盖主线程当前发送到 GL 的内存,并防止主线程发送未完成的数据。