Android 如何在 OpenGL ES 中有效地将一个纹理分配给另一个纹理

how to assign one texture to another efficiently in OpenGL ES for Android

我想将纹理 1 复制到纹理 2。背景是我生成15个空的纹理id绑定到GLES11Ext.GL_TEXTURE_EXTERNAL_OES,下面是我的代码:

int[] textures = new int[15];
GLES20.glGenTextures(15, textures, 0);
GlUtil.checkGlError("glGenTextures");

for(int i=0;i<15;i++)
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[i]);

然后我总是将相机预览转移到textures[0],我想将纹理从textures[0]复制到textures[1]以保持时间戳1的帧内容,并复制纹理从 textures[0]textures[2] 以保持时间戳 2 的帧内容...它看起来像在 GPU 中缓冲一些纹理数据并在将来渲染其中的一些。所以我想知道有没有办法做到这一点?我可以只使用 textures[2]=textures[0] 来复制纹理数据吗?

在 ES 2.0 中没有非常直接的方法来复制纹理数据。最简单的方法可能是使用 glCopyTexImage2D()。要使用它,您必须创建一个 FBO,并将源纹理附加到它。假设 srcTexId 是源纹理的 ID,而 dstTexId 是目标纹理的 ID:

GLuint fboId = 0;
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexId, 0);

glBindTexture(GL_TEXTURE_2D, dstTexId);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0);

话虽如此,根据您的描述,我不认为这真的是您应该做的,原因如下:

  • 我认为如上所示复制纹理数据不适用于您正在使用的外部纹理。
  • 复制纹理数据总是很昂贵,听起来完全没有必要解决您的问题。

听起来您想保留 15 张最近的相机图像。为此,您可以简单地跟踪 15 个纹理中的哪一个包含最新图像,并将 15 个纹理 ID 的列表视为循环缓冲区。

假设您最初创建纹理 ID:

int[] textures = new int[15];
GLES20.glGenTextures(15, textures, 0);
int newestIdx = 0;

然后每次收到新帧时,将其写入纹理 ID 列表中的下一个条目,在 15 处循环:

newestIdx = (newestIdx + 1) % 15;
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[newestIdx]);
// Capture new frame into currently bound texture.

然后,每次您想使用第 i 帧时,0 表示最近的帧,1 表示之前的帧,等等,您将其绑定为:

GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[(newestIdx + i) % 15]);

所以纹理永远不会被复制。您只需跟踪哪个纹理包含哪个帧,并相应地访问它们。