Android 如何在 OpenGL ES 中渲染深度纹理
How to render to a depth texture in OpenGL ES on Android
我需要渲染到 Android 中的深度纹理,但我无法弄清楚。我在网上搜索了几天,拼凑了以下代码:
public void loadFrameBuffer(Context context, int resourceId) {
final Bitmap bitmap = createBitmap(context, resourceId);
// generate the framebuffer and texture object names
glGenFramebuffers(1, frameBuffers, 0);
glGenTextures(2, textures, 0);
// bind color texture and load the texture mip level 0 texels are RGB565
// no texels need to specified as we are going to draw into the texture
glBindTexture(GL_TEXTURE_2D, textures[COLOR_TEXTURE]);
texImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// bind depth texture and load the texture mip level 0
// no texels need to specified as we are going to draw into
// the texture
glBindTexture(GL_TEXTURE_2D, textures[DEPTH_TEXTURE]);
texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// bind the framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffers[0]);
// specify texture as color attachment
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, textures[COLOR_TEXTURE],
0);
checkStatus();
// specify texture as depth attachment
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, textures[DEPTH_TEXTURE],
0);
checkStatus();
}
颜色附件的 checkStatus() 成功:GL_FRAMEBUFFER_COMPLETE
但是深度附件的 checkStatus() 是:GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
错误状态的文档:
Not all framebuffer attachment points are framebuffer attachment
complete. This means that at least one attachment point with a
renderbuffer or texture attached has its attached object no longer in
existence or has an attached image with a width or height of zero, or
the color attachment point has a non-color-renderable image attached,
or the depth attachment point has a non-depth-renderable image
attached, or the stencil attachment point has a non-stencil-renderable
image attached.
Color-renderable formats include GL_RGBA4, GL_RGB5_A1, and GL_RGB565.
GL_DEPTH_COMPONENT16 is the only depth-renderable format.
GL_STENCIL_INDEX8 is the only stencil-renderable format.
我很茫然,即使有了这个关于问题所在的描述。颜色附件效果很好。
编辑:
我在前面提到的状态错误之前的日志中看到了这一点:
<core_glTexImage2D:501>: GL_INVALID_OPERATION
看来是因为这行代码:
texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);
编辑:
我克服了错误。我从通话切换到:
texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);
这实际上是错误的,现在我打电话给:
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, texWidth, texHeight, 0,
GL_DEPTH_COMPONENT, GLES30.GL_FLOAT, null);
有效。我没有看到更多的错误。但是,我仍然遇到问题。
这是直接渲染到默认缓冲区的模型(直接渲染到 window):
但是当我尝试渲染附加到我的 FrameBuffer 的纹理映射到以下内容时:
// x, y, z, S, T
new float[]{
// left triangle
-1f, -1f, 0f, 0f, 0f, //
1f, 1f, 0f, 1f, 1f, //
-1f, 1f, 0f, 0f, 1f, //
// right triangle
-1f, -1f, 0f, 0f, 0f, //
1f, -1f, 0f, 1f, 0f, //
1f, 1f, 0f, 1f, 1f //
}
);
拉伸纹理:
如果我删除左边的三角形并进行渲染,我会得到:
最后,渲染深度纹理给了我所有的红色:
一切正常,无需修复
你的深度纹理是正确的。没有什么可以解决的了。
问题似乎是您期望对比度更高的东西。我下载了你的照片并在图像编辑器中增强了对比度:
你可以看到里面有细节!但是,这里丢失了大量数据。你的屏幕可能最多有一个 8 位帧缓冲区,然后我将结果下载为 JPEG 格式,进一步量化它,但是......原始深度纹理本身可能是 16 位。所以我猜想当我制作上面的图像时我们可能已经丢失了 ~10 位。
换句话说,深度缓冲区有16位精度,但屏幕只有8位。所以,你当然看不到细节。数据没问题
为什么是红色的?
当然是红色的。这是一张只有一个通道的图像。如果您想为其着色不同,请使用纹理调配,或在片段着色器中应用颜色。
我需要渲染到 Android 中的深度纹理,但我无法弄清楚。我在网上搜索了几天,拼凑了以下代码:
public void loadFrameBuffer(Context context, int resourceId) {
final Bitmap bitmap = createBitmap(context, resourceId);
// generate the framebuffer and texture object names
glGenFramebuffers(1, frameBuffers, 0);
glGenTextures(2, textures, 0);
// bind color texture and load the texture mip level 0 texels are RGB565
// no texels need to specified as we are going to draw into the texture
glBindTexture(GL_TEXTURE_2D, textures[COLOR_TEXTURE]);
texImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// bind depth texture and load the texture mip level 0
// no texels need to specified as we are going to draw into
// the texture
glBindTexture(GL_TEXTURE_2D, textures[DEPTH_TEXTURE]);
texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// bind the framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffers[0]);
// specify texture as color attachment
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, textures[COLOR_TEXTURE],
0);
checkStatus();
// specify texture as depth attachment
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, textures[DEPTH_TEXTURE],
0);
checkStatus();
}
颜色附件的 checkStatus() 成功:GL_FRAMEBUFFER_COMPLETE 但是深度附件的 checkStatus() 是:GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
错误状态的文档:
Not all framebuffer attachment points are framebuffer attachment complete. This means that at least one attachment point with a renderbuffer or texture attached has its attached object no longer in existence or has an attached image with a width or height of zero, or the color attachment point has a non-color-renderable image attached, or the depth attachment point has a non-depth-renderable image attached, or the stencil attachment point has a non-stencil-renderable image attached.
Color-renderable formats include GL_RGBA4, GL_RGB5_A1, and GL_RGB565. GL_DEPTH_COMPONENT16 is the only depth-renderable format. GL_STENCIL_INDEX8 is the only stencil-renderable format.
我很茫然,即使有了这个关于问题所在的描述。颜色附件效果很好。
编辑:
我在前面提到的状态错误之前的日志中看到了这一点:
<core_glTexImage2D:501>: GL_INVALID_OPERATION
看来是因为这行代码:
texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);
编辑:
我克服了错误。我从通话切换到:
texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, bitmap, 0);
这实际上是错误的,现在我打电话给:
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, texWidth, texHeight, 0,
GL_DEPTH_COMPONENT, GLES30.GL_FLOAT, null);
有效。我没有看到更多的错误。但是,我仍然遇到问题。
这是直接渲染到默认缓冲区的模型(直接渲染到 window):
但是当我尝试渲染附加到我的 FrameBuffer 的纹理映射到以下内容时:
// x, y, z, S, T
new float[]{
// left triangle
-1f, -1f, 0f, 0f, 0f, //
1f, 1f, 0f, 1f, 1f, //
-1f, 1f, 0f, 0f, 1f, //
// right triangle
-1f, -1f, 0f, 0f, 0f, //
1f, -1f, 0f, 1f, 0f, //
1f, 1f, 0f, 1f, 1f //
}
);
拉伸纹理:
如果我删除左边的三角形并进行渲染,我会得到:
最后,渲染深度纹理给了我所有的红色:
一切正常,无需修复
你的深度纹理是正确的。没有什么可以解决的了。
问题似乎是您期望对比度更高的东西。我下载了你的照片并在图像编辑器中增强了对比度:
你可以看到里面有细节!但是,这里丢失了大量数据。你的屏幕可能最多有一个 8 位帧缓冲区,然后我将结果下载为 JPEG 格式,进一步量化它,但是......原始深度纹理本身可能是 16 位。所以我猜想当我制作上面的图像时我们可能已经丢失了 ~10 位。
换句话说,深度缓冲区有16位精度,但屏幕只有8位。所以,你当然看不到细节。数据没问题
为什么是红色的?
当然是红色的。这是一张只有一个通道的图像。如果您想为其着色不同,请使用纹理调配,或在片段着色器中应用颜色。