1
\$\begingroup\$

I am trying to implement a simple deferred rendering engine in openGL and i have a little problem with the GBuffer. I cant get it to render to more than one texture at a single time, which is the one attached to GL_COLOR_ATTACHMENT0.

GBuffer initialization code:

    glGenFramebuffers(1,&m_FBO);
glBindFramebuffer(GL_FRAMEBUFFER,m_FBO);
//create Gbuffers
glEnable(GL_TEXTURE_2D);
//create diffusemap
glGenTextures(1,&m_Textures[GBUFFER_DIFFUSE_24]);
glBindTexture(GL_TEXTURE_2D,m_Textures[GBUFFER_DIFFUSE_24]);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,m_Width,m_Height,0,GL_RGB,GL_UNSIGNED_BYTE,0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,m_Textures[GBUFFER_DIFFUSE_24],0);
if(!glIsTexture(m_Textures[GBUFFER_DIFFUSE_24]))
    return false;
//create normalmap
glGenTextures(1,&m_Textures[GBUFFER_NORMAL24_MATID8]);
glBindTexture(GL_TEXTURE_2D,m_Textures[GBUFFER_NORMAL24_MATID8]);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB32F,m_Width,m_Height,0,GL_RGB,GL_FLOAT,NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT1,GL_TEXTURE_2D,m_Textures[GBUFFER_NORMAL24_MATID8],0);
if(!glIsTexture(m_Textures[GBUFFER_NORMAL24_MATID8]))
    return false;
//create depthmap
glGenTextures(1,&m_Textures[GBUFFER_DEPTH32]);
glBindTexture(GL_TEXTURE_2D,m_Textures[GBUFFER_DEPTH32]);
glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH24_STENCIL8,m_Width,m_Height,0,GL_DEPTH_STENCIL,GL_UNSIGNED_INT_24_8,0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT,GL_TEXTURE_2D,m_Textures[GBUFFER_DEPTH32],0);
if(!glIsTexture(m_Textures[GBUFFER_DEPTH32]))
    return false;
GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0,
                        GL_COLOR_ATTACHMENT1};
glDrawBuffers(2,drawBuffers);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

if(status != GL_FRAMEBUFFER_COMPLETE)
{
    printf("FBO error!!, status: 0x%x\n",status);
    return false;
}
glBindFramebuffer(GL_FRAMEBUFFER,0);

And then before i render all geometry i do this:

            glClearColor(0.2f,0.6f,0.3f,0);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER,m_FBO);
    GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0,
                            GL_COLOR_ATTACHMENT1};
    glDrawBuffers(2,drawBuffers);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT| GL_STENCIL_BUFFER_BIT);

And then after i rendered all of it i blit it to the normal framebuffer:

            RenderGeometry();
    glBindFramebuffer(GL_FRAMEBUFFER,0);
    glClearColor(0.0f,0.0f,0.0f,0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT| GL_STENCIL_BUFFER_BIT);
    glBindFramebuffer(GL_READ_FRAMEBUFFER,m_GBuffer->GetHandle());
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glBlitFramebuffer(0,0,1280,720,
        0,0,640,370,GL_COLOR_BUFFER_BIT,GL_LINEAR);

    glReadBuffer(GL_COLOR_ATTACHMENT1);
    glBlitFramebuffer(0,0,1280,720,
        640,370,640,370,GL_COLOR_BUFFER_BIT,GL_LINEAR);
    glfwSwapBuffers(m_Window);

And my fragment shader code is:

    #version 430

    in vec2 Tex;
    in vec3 Normal;

    uniform sampler2D   tex1;
    uniform bool        UseTexture;

    layout(location = 0) out vec3 FragmentColor;
    layout(location = 1) out vec3 FragmentNormal;

    void main()
    {
FragmentNormal.xyz = normalize(Normal);
if(UseTexture)
{
    FragmentColor = texture(tex1,Tex).rgb; //diffuse color
}
else
{
    FragmentColor = vec3(1,1,1);
}
    }

And the result is: Result

It should be two rectangles drawn to the screen one containing the diffuse color and one containing the screen normals. However i am only getting one.

\$\endgroup\$
1
  • \$\begingroup\$ By the way, if you want to visualize normals correctly you cannot blit them directly to screen. Since you're using a floating-point render target for the normals, they can store negative values. You need to use a shader that biases and scales them into the visible range for display (e.g. negative vectors get a color from [0.0-0.5] and positive get a color from [0.5-1.0]) \$\endgroup\$ Commented Sep 1, 2013 at 22:51

1 Answer 1

2
\$\begingroup\$

You are blitting your normal buffer into a 0x0 rectangle when you use:

glBlitFramebuffer(0,0,1280,720,640,370,640,370,GL_COLOR_BUFFER_BIT,GL_LINEAR);

You are also wasting memory bandwidth by writing your normals using 32-bit floating-point. You can get away with 8-bit fixed-point most of the time, and when you cannot you should try an RGBA_10_2 or half-float (16-bit) format before jumping straight to 32-bit floating-point.

Also, make sure to bias and scale your normals before showing them on screen for the purpose of visual inspection. They can have negative values, which will be outside the visible color range. The normal way of tackling this is to multiply by 0.5 and add 0.5.

Judging by the name you're using for your texture ID, you probably meant to use an RGBA8 format for normals and pack the material ID into the A channel. In which case you need to write your normals the way I described above and then unpack them using: normal = 2.0 * (normal - vec3 (0.5))

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .