0
votes

I try to render my geometry in the first pass and render it from a buffer to a quad in my second pass.
Rendering the geometry directly to screen works, but as soon as I try to render to the quad with multiple passes, the screen stays black (the clear-color is grey).
I think my shader might be the problem. Please just ask for more code if needed.

Vertex Shader:

#version 440

layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexUV;
layout(location = 2) in vec3 vertexNormal;

centroid out vec2 UV;
out vec4 position;
out vec3 normal;

uniform mat4 uniMatModel;
uniform mat4 uniMatView;
uniform mat4 uniMatProjection;
uniform mat4 uniMatModelView;
uniform mat4 uniMatModelViewProjection;
uniform mat3 uniMatNormal;

void main()
{
    UV = vertexUV;
    position = uniMatModelView * vec4(vertexPosition, 1.0);
    normal = normalize(uniMatNormal * vertexNormal);
    gl_Position = uniMatModelViewProjection * vec4(vertexPosition, 1.0);
}



Fragment Shader:

#version 440

centroid in vec2 UV;
in vec4 position;
in vec3 normal;

layout (location = 0) out vec4 fragColor;
layout (location = 1) out vec3 positionData;
layout (location = 2) out vec3 normalData;
layout (location = 3) out vec3 colorData;

subroutine void renderPassType();
subroutine uniform renderPassType renderPass;

uniform sampler2D uniSamTexture;
uniform sampler2D uniSamAlpha;

layout(binding = 0) uniform sampler2D positionTex;
layout(binding = 1) uniform sampler2D normalTex;
layout(binding = 2) uniform sampler2D colorTex;

subroutine (renderPassType)
void renderWorld()
{
    if (texture2D(uniSamAlpha, UV).rgb[0] == 1.0) // Alphamaps have to be inverted!
    {
        discard;
        colorData = vec3(0.0);
    }
    else
    {
        colorData = texture2D(uniSamTexture, UV).rgb;
    }

    positionData = vec3(position.x, position.y, position.z);
    normalData = normal;
}

subroutine (renderPassType)
void renderLight()
{
    fragColor = vec4(texture(colorTex, UV).rgb, 1.0);
}

void main()
{
    renderPass();
}



Edit:

void C0::Cocaine::makeFBO(GLuint &fbo)
{
    GLuint depthBuf;
    Texture
        posTex(this),
        normTex(this),
        colorTex(this)
    ;

    // Create and bind the FBO
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    // The depth buffer
    glGenRenderbuffers(1, &depthBuf);
    glBindRenderbuffer(GL_RENDERBUFFER, depthBuf);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, static_cast<GLsizei>(resolution.x), static_cast<GLsizei>(resolution.y));

    // Create the textures for position, normal and color
    posTex.createGBuf(GL_TEXTURE0, GL_RGB32F, static_cast<int>(resolution.x), static_cast<int>(resolution.y));
    normTex.createGBuf(GL_TEXTURE1, GL_RGB32F, static_cast<int>(resolution.x), static_cast<int>(resolution.y));
    colorTex.createGBuf(GL_TEXTURE2, GL_RGB8, static_cast<int>(resolution.x), static_cast<int>(resolution.y));

    // Attach the textures to the framebuffer
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuf);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, posTex.getTextureID(), 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normTex.getTextureID(), 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, colorTex.getTextureID(), 0);

    GLenum drawBuffers[] = { GL_NONE, GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
    glDrawBuffers(4, drawBuffers);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}


void C0::Texture::createGBuf(GLenum texUnit, GLenum format, int width, int height)
{
    this->width = width;
    this->height = height;
    glActiveTexture(texUnit);
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}



Edit: The render method:

void C0::Mesh::render()
{
    if (shader != nullptr)
    {
        shader->use();
        shader->setModelMatrix(modelMatrix);
    }

    glBindVertexArray(VAO);

    if (!is2D)
    {
        for (int i = 0x1; i <= 0xB; i++)
        {
            if (texture[i] != nullptr)
            {
                glBindMultiTextureEXT(GL_TEXTURE0 + i, GL_TEXTURE_2D, texture[i]->getTextureID());
            }
        }
    }

    glDrawArrays(GL_TRIANGLES, 0, indexCount);
    glBindVertexArray(0);
}



More code:

pass1->setRenderCallback([&]() {

    sp->useSubRoutine(srp1);
    cube->render();

    return true;
});

pass2->setRenderCallback([&]() {

    sp->useSubRoutine(srp2);
    sp->resetMatrices(); // it should be a 2D quad, so I reset the MVP uniforms to 1.0f
    sp->lockMVP(true); // workaround (still playing around with everything)
    dq->render(); // render display quad
    sp->lockMVP(false);

    return true;
});

e->setOnRender([&]() {

    pass1->render();
    pass2->render();

    /* handle input etc... */
});



Pass render method:

bool Pass::render()
{
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    if (depthTest)
    {
        glEnable(GL_DEPTH_TEST);
    }
    else
    {
        glDisable(GL_DEPTH_TEST);
    }

    if (onRender != nullptr)
    {
        if (!onRender())
        {
            return false;
        }
    }

    if (fbo != 0)
    {
        glFinish();
    }

    return true;
}
1
Please do not edit your question to fix the problems pointed out in the answers. It invalidates the answers.Reto Koradi
Have you checked if the seperate images are rendered correctly?Anton D
@RetoKoradi: It is not the answer...Marco Alka
@AntonD: what do you mean by separate images?Marco Alka
@MarcoAlka Normally when writing a deferred renderer you render to multiple images in the first pass, and then use those images to create a final image in the second pass. Examples of those images are the color texture, the normal texture, the position texture and others. As a debugging step you can render those seperate images to the screen to test if the first pass was succesfull. Could you give more info about your implementation?Anton D

1 Answers

2
votes

With the shader version string you use:

#version 440

the default for the profile is core. From the GLSL 4.40 spec:

A profile argument can only be used with version 150 or greater. If no profile argument is provided and the version is 150 or greater, the default is core.

The texture2D() function you are calling in the fragment shader is only available in the compatibility profile. In the core profile, you need to use the overloaded texture():

if (texture(uniSamAlpha, UV).rgb[0] == 1.0) // Alphamaps have to be inverted!
...
    colorData = texture(uniSamTexture, UV).rgb;

If you have problems with your shaders, it's always a good idea to check that the compilation was successful. You can use the following calls for this:

glGetShaderiv(shaderId, GL_COMPILE_STATUS, ...);
glGetShaderInfoLog(shaderId, ...);