1
$\begingroup$

I want to do some complicated stuff but have problems with my geometry shader / FBO bindings. To hold it as easy as possible I reduced the code to a minimum. If this works, I could continue the hard part. So don't wonder, why I am trying to do it in this way...

The "easy" thing:

I have two triangles (a quad) which are going over the whole screen from (-1,-1,0) to (1,1,0). Inside my geometry shader I want to copy these two triangles six times to cover all six faces of my cubemap. BTW: I don't need a depth or stencil buffer.

Lets look at the cubemap texture generation:

glGenTextures(1, &m_cubeMapTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_cubeMapTexture);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
checkGLError();
// set textures
for (int i = 0; i < 6; ++i)
    glTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i), 0, GL_RGB, 2048, 2048, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);

This texture will be plugged into a frameBufferObject in the following way:

glGenFramebuffers(1, &m_cubeMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, m_cubeMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, m_cubeMapTexture, 0);

static const GLuint draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 };
glDrawBuffers(6, draw_buffers);

The vertex shader:

#version 420
in vec3 POSITION;
                                                                                
out VS_OUT                                                            
{                                                                    
   vec3 position;                                                     
} vs_out;                                                            
                                                                                
void main()                                                           
{                                                                   
    vs_out.position = POSITION;  
}

Just take the input and pass it to the geometry shader

Lets continue with the geometry shader:

#version 420                                                        
layout (triangles) in;                                               
layout (triangle_strip, max_vertices = 36) out;                     
uniform mat3 orientation[6];                                        
                                                                              
in VS_OUT                                                           
{                                                                   
    vec3 position;                                                   
} gs_in[];                                                        
                                                                              
out GS_OUT                                                         
{                                                                   
    vec3 position;                                                    
} gs_out;                                                          
                                                                              
void main()                                                          
{                                                                  
    for (int i = 0; i < 6; ++i)                                     
    {                                                                
        gl_Layer = i;                                              
        gl_Position = vec4(gs_in[0].position, 1.0f);                
        gs_out.position = orientation[i] * vec3(gs_in[0].position.xy, 1.0f);      
        EmitVertex();                                               
                                                                              
        gl_Layer = i;                                                
        gl_Position = vec4(gs_in[1].position, 1.0f);                 
        gs_out.position = orientation[i] * vec3(gs_in[1].position.xy, 1.0f);        
        EmitVertex();                                              
                                                                              
        gl_Layer = i;                                                
        gl_Position = vec4(gs_in[2].position, 1.0f);                
        gs_out.position = orientation[i] * vec3(gs_in[2].position.xy, 1.0f);        
        EmitVertex();                                                
                                                                              
        EndPrimitive();                                              
    }                                                               
}     

The for loop creates each triangle six times (one for each cubemap face "gl_Layer = i"). the gl_Position is the input quad without any transformations. the gs_out.position is rotated by the orientation matrix (a rotation matrix for each face). This gs_out.position should be interpolated within the fragment shader.

Last, but not least: The fragment shader

#version 420                                             
in GS_OUT                                              
{                                                    
    vec3 position;                                       
} fs_in;                                                
                                                                  
out vec4 color;                                     
                                                                  
void main()                                            
{                                                      
    color = vec4(fs_in.position, 1.0f);                
}          

The interpolated fs_in.position will be stored into the cubemap.

If you just look at the code and try to imagine what the output should be, you'll end up to say: "That is the RGB cube + the minus part which is stored in the cubemap."

And now I'll show you the output:

enter image description here

My first intention was changing the "orientation" matrices but I noticed, that this is not the problem: By changing the for loop counter within my geometry shader to "for (int i = 0; i < 1; ++i)" I got the following output:

enter image description here

So there are only the two triangles, which are not copied anymore and each cubemap face is colored in the same way. gl_Layer was only set to zero but the other layers are also colored. How can that be? How can I change the code, so that only the face "gl_Layer" will be colored?

$\endgroup$

1 Answer 1

2
$\begingroup$

After trying everything possible I found my mistake:

The shaders are fine, the only thing which is wrong is the frameBufferObject binding. To be honest, the texture to FBO binding.

the only thing I replaced is this:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, m_cubeMapTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, m_cubeMapTexture, 0);

by the correct method call:

glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_cubeMapTexture, 0);
    

The result of the changed code is this:

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.