Opengl-后处理多个FBO-我在做什么错?

时间:2018-07-05 19:31:18

标签: java opengl graphics lwjgl fbo

我是OpenGL的新手。我以为我了解FBO,但是我很难使它们起作用。

我的程序绘制了多次采样的fbo基本图形信息(colorFbo)。 从colorFbo我将blit到postprocessFbo。 然后是带有无符号int值的counterFbo,我在其中简单地用对象的ID填充每个对象的轮廓。

我想对postprocessFbo和counterFbo进行后处理,但是,我看不到counterFbo的任何作用...请问问题出在哪里? 这是我的代码的一部分:

初始化:

colorFbo = new Framebuffer(true, false);   //multisampled, rgba
counterFbo = new Framebuffer(false, true); //not MS, red

...seting polygonmode, viewport, depthtest, blending...   

modelProgram = loadProgram("model");
counterProgram = loadProgram("counter");
...
postprocessProgram = loadProgram("postprocess");
...        
postprocessFbo = new Framebuffer(false, false); //not MS, rgba

渲染循环:

glBindFramebuffer(GL_FRAMEBUFFER, colorBuffer.fbo());
Main.clear(0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);        
drawing objects using model program...

glBindFramebuffer(GL_FRAMEBUFFER, counterBuffer.fbo());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_MULTISAMPLE);        
drawing objects using counter program...

blit colorFbo to postprocessFbo...

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glUseProgram(postprocessProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, postprocessFbo.fboColorTexture());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, counterFbo.fboColorTexture());

glBindVertexArray(screenQuadArray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);        

计数器片段着色器:

#version 330

out uint counter;

in vec3 vPosition;

uniform uint id;

void main() {
    counter = id;
}

后处理片段着色器:

#version 330

uniform sampler2D colorTex;
uniform usampler2D counterTex;

out vec4 finalColor;

in vec2 texCoord;

void main() {
    finalColor = texture(colorTex, vec2(tex));
    uint id = texture(counterTex, vec2(tex)).s;
    if (id > 0) {
        finalColor = black;
    }
}

帧缓冲构造函数:

public Framebuffer(boolean multisampled, boolean redOnly) {
    int internalFormat = redOnly ? GL_R32UI : GL_RGBA;
    int format = redOnly ? GL_RED_INTEGER : GL_RGBA;
    int dataType = redOnly ? GL_UNSIGNED_INT : GL_UNSIGNED_BYTE;
    int interpolation = redOnly ? GL_NEAREST : GL_LINEAR;

    int textureType = multisampled ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
    // Prepare FBO textures
    fboColorTexture = glGenTextures();
    fboDepthStencilTexture = glGenTextures();
    if (multisampled) {
        glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboColorTexture);
        glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, SAMPLES, internalFormat, Main.width(), Main.height(), false);
        glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboDepthStencilTexture);
        glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, SAMPLES, GL_DEPTH24_STENCIL8, Main.width(), Main.height(), false);            
        glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
    } else {
        glBindTexture(GL_TEXTURE_2D, fboColorTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, Main.width(), Main.height(), 0, format, dataType, (float[]) null);            
        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_MIN_FILTER, interpolation);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolation);
        glBindTexture(GL_TEXTURE_2D, fboDepthStencilTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, Main.width(), Main.height(), 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, (float[]) null);
        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_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glBindTexture(GL_TEXTURE_2D, 0);
    }        

    fbo = glGenFramebuffers();
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureType, fboColorTexture, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, textureType, fboDepthStencilTexture, 0);
    glDrawBuffers(GL_COLOR_ATTACHMENT0);
    int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) {
        System.err.println("Framebuffer not complete.");
        System.exit(1);
    }
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

2 个答案:

答案 0 :(得分:1)

您似乎缺少将纹理单位分配给纹理名称的想法。因此,当我加载纹理时,通常在初始化时执行此操作...

uColorTex = glGetUniformLocation(shaders.shaderProgram, "colorTex");
uCounterTex = glGetUniformLocation(shaders.shaderProgram, "counterTex");

...以及绘图时...

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, postprocessFbo.fboColorTexture());
glUniform1i(uColourTex, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, counterFbo.fboColorTexture());
glUniform1i(uCounterTex, 1);

答案 1 :(得分:0)

问题出在计数器程序本身(在glVertexAttribPointer中),我没有写过。 我只需要在计数器程序中定位即可,所以我这样写:

glVertexAttribPointer(positionAttribLoc, 3, GL_FLOAT, false, FLOAT_VEC3_SIZE, 0);

但是我忘记了,数据始终位于同一位置,所以我不能“节省空间”,因为我只是绑定,所以顶点数据保持不变:

glVertexAttribPointer(positionAttribLoc, 3, GL_FLOAT, false, SIZEOF_MODEL_VERTEX, 0);

感谢您的回答,对不起,我没有显示更多代码,我认为问题可能出在任何地方,不想让阅读过多代码的人不知所措。