opengl - 根据软件渲染器生成的 2D 视觉填充深度缓冲区
问题描述
我的情况是这样的:作为 2D 纹理的 2D 图像是由软件渲染器生成的,该渲染器实际上展示了“3D”视觉效果。然后,OpenGL 基本上仅用于显示此 2D 纹理。结果,尽管渲染了看似 3D 的视觉效果,但无论我如何使用着色器渲染深度缓冲区,它都无法完成,因为那里实际上什么都没有。我想访问深度缓冲区以启用此类着色器。
所以,我想以某种方式根据我的图像填充深度缓冲区。我认为这可能是可行的,因为有问题的软件渲染器可以生成“深度图”图像及其“常规”图像作为渲染模式 - 深度图图像看起来与深度缓冲区的渲染完全一样(灰度,靠近相机的物体是黑色的)。所以我想我的问题是:我是否可以将代表深度的“预渲染”图像转换为深度缓冲区?我怎么能这样做呢?
编辑:如果这有帮助,我专门使用 OpenGL 3.3。
编辑 2:继续研究我可以在这里做什么我发现这个讨论建议我“使用帧缓冲区对象或写入 gl_FragDepth 的片段着色器”。然而,讨论很快让我有点难以消化,我想我理解写入 gl_FragDepth 的片段着色器的概念,但是这在实践中是如何工作的?
我在想我做类似下面的伪代码?
program = createProgram(); //write to gl_FragDepth in the frag shader
glUseProgram(program);
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
glEnable(GL_DEPTH_TEST);
glGenTextures(1, &depth_texture);
glBindTexture(GL_TEXTURE_2D, depth_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depth->width, depth->height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, depth->pixels)
glDisable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, 0);
我需要启用深度测试吗?
编辑3:
如果我理解正确,在做了更多阅读之后,我认为我需要做以下事情,但是我不能让它工作。这里的某些东西看起来明显不正确吗?我发现正在发生的事情是在片段着色器中 sampler2Dstex0
并tex1
以某种方式包含相同的值,因此,我要么能够将颜色值写入颜色,gl_FragDepth
要么将深度值写入颜色,这会产生有趣但无益的结果。
总结片段着色器:
out vec4 color;
uniform sampler2D tex0; // color values
uniform sampler2D tex1; // depth values
void main(void) {
color = texture(tex0, uv);
gl_FragDepth = texture(tex1, uv).z;
}
总结OpenGL:
// declarations
static GLuint vao;
static GLuint texture = 1;
static GLuint depth_texture = 2;
// set up shaders
program = createProgram();
glUseProgram(program); //verified that this is working
// enable depth testing
glEnable(GL_DEPTH_TEST);
// prepare dummy VAO
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// prepare texture for color values
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// prepare texture for depth values
glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &depth_texture);
glBindTexture(GL_TEXTURE_2D, depth_texture);
// disable depth mask while working with color values
glDepthMask(GL_FALSE);
// select GL_TEXTURE0 and bind the color values
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
// specify texture image for colorvalues
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, TEX_FORMAT, TEX_TYPE, fb->pixels);
// enable depth mask while working with depth values
glDepthMask(GL_TRUE);
// select GL_TEXTURE1 and bind the depth values
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depth_texture);
// specify texture image for depth values
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, TEX_FORMAT, TEX_TYPE, fb->depth);
// draw
glViewport(win_x, win_y, win_width, win_height);
glDrawArrays(GL_TRIANGLES, 0, 3);
解决方案
我想指出 Ripi2 的回答真正引导我完成了这个问题,但是我想我会写一个答案来解决我的问题,我最终需要做什么,我的问题出了什么问题,现在找到了我的方式通过这个问题。
首先,我的问题有什么问题?我对 OpenGL 纹理有几个误解——但最根本的是。我将纹理误解为图像的“容器”,我现在的理解是它是一个缓冲区,并且可以包含除了简单的“图像”之外的信息(例如,纹理可以存储 z 深度数据)。
我的问题仍然存在,正如我所理解的那样:我有两张预渲染的图像,一张说明颜色数据,一张说明深度缓冲区数据。为了解决这个问题,首先我必须了解如何管理两种纹理:一种包含颜色数据,另一种包含深度数据,这样我就可以对它们进行采样。
我在我的 OpenGL 代码中缺少的内容(来自我对问题的第三次编辑)基本上如下:
// get the uniform variables location
depthValueTextureLocation = glGetUniformLocation(program, "DepthValueTexture");
colorValueTextureLocation = glGetUniformLocation(program, "ColorValueTexture");
// specify the shader program to use
glUseProgram(program);
// bind the uniform variables locations
glUniform1i(depthValueTextureLocation, 0);
glUniform1i(colorValueTextureLocation, 1);
我的 Frag 着色器采样器最终看起来像这样匹配:
uniform sampler2D ColorValueTexture;
uniform sampler2D DepthValueTexture;
只是在这一点上,我A)现在不仅拥有纹理,而且还了解如何在我的着色器中对它们进行采样,并且B)将我的数据放在正确的位置,这样我就可以了解我在绘图时到底发生了什么。我看到了一个令人困惑的结果,其中一个纹理的数据似乎出现在另一个纹理中,我也能够通过将“绘图阶段”分成两个较小的阶段来解决这个问题,如下所示:
首先我使用颜色纹理绘制:
// select the color value binding
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, texture);
// draw
glDrawArrays(GL_TRIANGLES, 0, 3);
然后我使用深度纹理进行绘制:
// select the depth value binding
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, depth_texture);
// draw
glEnable(GL_DEPTH_TEST);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisable(GL_DEPTH_TEST);
重要的是要注意,我只在使用深度纹理时才启用深度测试!
推荐阅读
- julia - Documenter.jl:在@index 块中添加参数
- python - 如何在 AWS Lambda 中获取当前时间戳?
- pytorch - PyTorch CUDA 错误:遇到非法内存访问
- python - 使用 PyPDF2 拆分 PDF 会从图像中删除替代文本
- javascript - OpenLayers 6 具有大量点的高频率层更新
- javascript - 如何设置安全规则以防止 Firebase 中其他用户更新数据
- reactjs - 我正在尝试在我的项目页面(react js)组合中实现“阅读更多”链接
- c# - 在 C# 中使用 JSONWebKey 或 JSONWebKeySet 解密 JSONWebToken
- maven - 通过 Jenkins + Maven 运行 Appium 测试时无法初始化 iOS 驱动程序
- python - 计算圆内的直方图值(houghcircles)