c++ - OpenGL:将 FBO 的深度纹理绑定(bind)到计算着色器

标签 c++ opengl glsl fbo depth-buffer

我一直在尝试渲染到一个 FBO 并将两个 FBO 渲染到屏幕上,但是在两个 FBO 的合并处进行深度测试一直没有成功。我已经尝试将纹理与计算着色器合并,但我无法读取深度纹理的值(所有值均为值 1,但当我渲染到 FBO 时深度测试正在运行)。有谁知道我做错了什么,或者知道合并两个 FBO 的其他方法吗?

这就是我创建 FBO 的方式:

struct FBO {
    uint color;
    uint depth;
    uint fbo;
};
FBO createFBO(int width, int height) {
    FBO fbo;
    fbo.color = createFBOTexture(width, height, false);
    fbo.depth = createFBOTexture(width, height, true);
    fbo.fbo = generateFramebuffer(fbo.color, fbo.depth);

    return fbo;
}
uint createFBOTexture(int width, int height, bool isDepthBuffer) {
    uint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    if (isDepthBuffer)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    else
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_FLOAT, NULL);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    int i = glGetError();
    if (i)
    std::cout << "Error while creating the FBO: " << gluErrorString(i) << '\n';

    return texture;
}
uint generateFrameBuffer(uint color, uint depth)
{
    int mipmapLevel = 0;

    //Generate FBO
    uint fbo;
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    //Attatch textures to the FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, mipmapLevel);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, mipmapLevel);

    //Error check
    int i = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (i != GL_FRAMEBUFFER_COMPLETE)
        std::cout << "ERROR: frambuffer is not ok, status: " << i << '\n';
    else {
        int i = glGetError();
        if (i)
            std::cout << "Error while creating the FBO: " << gluErrorString(i) << '\n';
    }
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    return fbo;
}

这是我呈现给 FBO 的方式:

glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);

glBindFramebuffer(GL_FRAMEBUFFER, fbo_pointcloud.fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawPointCloud(); //Here I draw points with the depreciated fixed pipeline
glFlush();

我尝试使用 glBindTexture 绑定(bind)纹理(所有值都读取为 1):

void MergeFrames::merge(TextureLoading::FBO tex0, TextureLoading::FBO tex1, GLuint result, int width, int height)
{
    glUseProgram(shader);

    //Bind depth textures
    glActiveTexture(GL_TEXTURE0+0);
    glBindTexture(GL_TEXTURE_2D, tex0.depth);
    glActiveTexture(GL_TEXTURE0+1);
    glBindTexture(GL_TEXTURE_2D, tex1.depth);

    //Bind color textures
    glBindImageTexture(2, tex0.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
    glBindImageTexture(3, tex1.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
    glBindImageTexture(4, result, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);

    //Dispatch the shader
    glDispatchCompute(ceilf(width / 16.0f), ceilf(height / 16.0f), 1);
}

计算着色器:

#version 430

uniform sampler2D depthTex0;
uniform sampler2D depthTex1;
uniform layout(rgba8) readonly image2D colorTex0;
uniform layout(rgba8) readonly image2D colorTex1;
uniform layout(rgba8) writeonly image2D mergedColor;

layout (local_size_x = 16, local_size_y = 16) in;

void main() {
    ivec2 ID = ivec2(gl_GlobalInvocationID.xy); 
    ivec2 size = imageSize(colorTex0);
    vec2 texCoords = vec2(float(ID.x)/float(size.x),float(ID.y)/float(size.y));

    float depths[2];
    vec4 colors[2];

    depths[0] = texture2D(depthTex0, texCoords).x;
    depths[1] = texture2D(depthTex1, texCoords).x;

    colors[0] = imageLoad(colorTex0, ID);
    colors[1] = imageLoad(colorTex1, ID);

    int i = int(depths[1] > depths[0]);
    imageStore(mergedColor, ID, colors[i]);
}

我尝试使用 glBindTexture 绑定(bind)纹理(所有值都读取为 0):

void MergeFrames::merge(TextureLoading::FBO tex0, TextureLoading::FBO tex1, GLuint result, int width, int height)
{
    glUseProgram(shader);

    glBindImageTexture(0, tex0.color, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
    glBindImageTexture(1, tex1.color, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
    glBindImageTexture(2, tex0.depth, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R16);
    glBindImageTexture(3, tex1.depth, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R16);
    glBindImageTexture(4, result, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);

    glDispatchCompute(ceilf(width / 16.0f), ceilf(height / 16.0f), 1);
}

计算着色器:

#version 430

uniform layout(rgba8) readonly image2D colorTex0;
uniform layout(rgba8) readonly image2D colorTex1;
uniform layout(r16) readonly image2D depthTex0;
uniform layout(r16) readonly image2D depthTex1;
uniform layout(rgba8) writeonly image2D mergedColor;

layout (local_size_x = 16, local_size_y = 16) in;

void main() {
    ivec2 ID = ivec2(gl_GlobalInvocationID.xy); 

    float depths[2];
    vec4 colors[2];

    colors[0] = imageLoad(colorTex0, ID);
    depths[0] = imageLoad(depthTex0, ID).x;

    colors[1] = imageLoad(colorTex1, ID);
    depths[1] = imageLoad(depthTex1, ID).x;

    int i = int(depths[1] < depths[0]);
    imageStore(mergedColor, ID, colors[i]);
}

这就是我绑定(bind)索引的方式(索引在我使用 sampler2D 而不是 image2D 的版本中有所不同):

MergeFrames::MergeFrames()
{
    shader = OpenGL::compileComputeShader("MergeFrames.comp");

    glUseProgram(shader);

    glUniform1i(glGetUniformLocation(shader, "colorTex0"), 0);
    glUniform1i(glGetUniformLocation(shader, "colorTex1"), 1);
    glUniform1i(glGetUniformLocation(shader, "depthTex0"), 2);
    glUniform1i(glGetUniformLocation(shader, "depthTex1"), 3);
    glUniform1i(glGetUniformLocation(shader, "mergedColor"), 4);
}

最佳答案

我通过在渲染后将数据从深度纹理复制到格式为 GL_RED 的纹理来使代码正常工作。

关于c++ - OpenGL:将 FBO 的深度纹理绑定(bind)到计算着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41394587/

相关文章:

c++ - 如何安全地删除 std::vector 中的元素

c++ - 关闭 Eclipse 错误(不是真正的错误)

opengl - OpenGL 中的轨迹球旋转

javascript - 如何从 Javascript/THREE.js 编码和发送 float 据到 GLSL 并解码结果

c++ - 了解 C++ 中的初始化顺序

delphi - 什么可以使带有 VBO 的 glDrawArrays 无法绘制任何内容?

java - 按请求绘制而不是使用指定的 fps 绘制

c - View (lookat)和投影(perspective)矩阵无法正常工作

c++ - 视差映射 - GLSL- OpenGL

java - Java 内存模型和 C++11 内存模型有什么相似之处?