Layered rendering cubemap

Hello,

I try to do layered rendering with framebuffers but I have trouble.

I try to implement cubemap (render to texture) but it doesn’t work like expected. All I get is a black cubemap I don’t understand why.
What I want is to dynamically change the texture (like wave simulation, etc…)

this is how I initialize a texture :

    glGenTextures(1, &texture_cubemap);
    glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);

    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);

    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

the framebuffer:


    glGenFramebuffers(1, &_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
    for(i = 0; i < 6; i++)
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, texture_cubemap, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

And my shaders :

The vertex shader :

#version 330

layout (location = 0) in vec3 positionsPoints;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

void main(){
gl_Position = vec4(positionsPoints, 1);
}

The geometry shader with gl_layer :


#version 330

layout(points) in;
layout(points, max_vertices = 1) out;
uniform mat4 projectionMatrix;

//out vec3 fsotexCoord;

out vec4 colorPoint;

void main(void) {
    int i, layer;
    for (layer = 0; layer < 6; layer++) {
        gl_Layer = layer;
        for (i = 0; i < gl_in.length(); i++) {
            gl_Position = gl_in[0].gl_Position;//vec4(, 1);//projectionMatrix *
            colorPoint = vec4(1, 0, 0, 1);
            EmitVertex();
        }
        EndPrimitive();
    }
}

and the fragment :

#version 330

in vec4 colorPoint;

out vec4 fragColor;

void main() {
    fragColor = colorPoint;
}

If I set an array of vertices in glTexImage2D (instead of NULL) I have something but that mean that gl_layer doesn’t work and I don’t understand why…

Thanks for the help.

Try changing [var]max_vertices[/var] to 6. The value is the maximum number of vertices emitted by one invocation of the geometry shader, not for a single primitive.



    for(i = 0; i < 6; i++)
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, texture_cubemap, 0);

This is not a layered framebuffer. This is attaching 6 images from one texture to 6 different attachments in the FBO.

A layered framebuffer, a requirement for layered rendering, means attaching a single mipmap level containing multiple images to the same attachment. You have to use glFramebufferTexture to attach images for layered rendering. And if you’re using a depth buffer, you need a layered depth buffer too.

6 for the face of a quad ? I thought that the geometry shader is for the output of what we draw. For example if I draw a triangle the max_vertices will be 3… No ?

[QUOTE=Alfonse Reinheart;1293215]



    for(i = 0; i < 6; i++)
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, texture_cubemap, 0);

This is not a layered framebuffer. This is attaching 6 images from one texture to 6 different attachments in the FBO.

A layered framebuffer, a requirement for layered rendering, means attaching a single mipmap level containing multiple images to the same attachment. You have to use glFramebufferTexture to attach images for layered rendering. And if you’re using a depth buffer, you need a layered depth buffer too.[/QUOTE]

I tried with glFramebufferTexture but glCheckFramebufferStatus return me false …

EDIT : It returned false because I set “GL_COLOR_ATTACHMENT0” instead of “GL_TEXTURE_CUBE_MAP_POSITIVE_X” but same result it stay black

You’re generating six output vertices for each invocation of the geometry shader, one for each layer. If you were generating triangles, you’d need max_vertices=18 (assuming each invocation converts one input triangle to six output triangles).

But not having a layered framebuffer (as Alfonse points out) is the bigger issue here.

Ok, I think I see… But we agree that the geometry shader is not attach to the skybox, right ?
Because I don’t know if it’s related but here is how my shaders is linked :


    pIdSkybox = gl4duCreateProgram("<vs>skybox/skybox.vs.glsl", "<fs>skybox/skybox.fs.glsl");
    pIdPoints = gl4duCreateProgram("<vs>Points/Points.vert", "<gs>Points/Points.geom", "<fs>Points/Points.frag");

My geometry shader is not attach to the skybox but to the grid of points I want to draw.

But not having a layered framebuffer (as Alfonse points out) is the bigger issue here.

I did it but nothing changed… here is my change :


    glGenFramebuffers(1, &_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
    glGenTextures(1, &texture_cubemap);
    glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // depth cube map
/*
    glGenTextures(1, &_depthFbo);
    glBindTexture(GL_TEXTURE_CUBE_MAP, _depthFbo);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    for (uint face = 0; face < 6; face++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_DEPTH_COMPONENT24,
                     256, 256, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
    }
*/

//    glGenRenderbuffers(1, &_depthFbo);
//    glBindRenderbuffer(GL_RENDERBUFFER, _depthFbo);
//    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 256, 256);
//    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthFbo);

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_cubemap, 0);
//    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _depthFbo, 0);

    GLenum drawBuffers[1] = {GL_COLOR_ATTACHMENT0};
    glDrawBuffers(1, drawBuffers);