This question is related to another question of mine on StackOverflow.
The problem I'm facing is that while I'm rendering to a cubemap in a single pass using a geometry shader (like I show in my other question) only the positive X face of the cube map actually gets rendered.
Using NSight I could see that actually also my negative X face is being rendered (with the right color looking to the pixel history), but then it results to be completely black, like if the fragment is discarded.
Doing some tests, I've found that this problem may be due to a glViewport
call that I do when I bind the framebuffer of the destination cube map as the rendering target. My destination cube map is a 256x256 pixels cube map (every face is 256x256 pixels wide) and calling glViewport(0, 0, 256, 256)
doesn't work (it renders only the positive X face like I said befare), but calling glViewport(0, 0, 181, 181)
and below (with width and height less than 181) also the negative X face is rendered.
Every call to glViewport
passing width and height more than 181 doesn't work.
Could this be a driver problem? I'm facing this problem ONLY when rendering to the cube map bound to the framebuffer as GL_TEXTURE_CUBE_MAP
target, if I bind every face with GL_TEXTURE_CUBE_MAP_POSITIVE_X, ...
as target and draw to it there's no problem.
UPDATE
This is my geometry shader (this handles only the positive and negative X faces):
#version 330 core
layout(points) in;
layout(triangle_strip, max_vertices = 8) out;
out vec3 frag_textureCoord;
void main()
{
const vec4 positions[4] = vec4[4] ( vec4(-1.0, -1.0, 0.0, 1.0),
vec4( 1.0, -1.0, 0.0, 1.0),
vec4(-1.0, 1.0, 0.0, 1.0),
vec4( 1.0, 1.0, 0.0, 1.0) );
// Positive X
gl_Layer = 0;
gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);
frag_textureCoord = vec3(1.0, 1.0, -1.0);
EmitVertex();
gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);
frag_textureCoord = vec3(1.0, 1.0, 1.0);
EmitVertex();
gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);
frag_textureCoord = vec3(1.0, -1.0, -1.0);
EmitVertex();
gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);
frag_textureCoord = vec3(1.0, -1.0, 1.0);
EmitVertex();
EndPrimitive();
// Negative X
gl_Layer = 1;
gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);
frag_textureCoord = vec3(-1.0, 1.0, -1.0);
EmitVertex();
gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);
frag_textureCoord = vec3(-1.0, 1.0, 1.0);
EmitVertex();
gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);
frag_textureCoord = vec3(-1.0, -1.0, -1.0);
EmitVertex();
gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);
frag_textureCoord = vec3(-1.0, -1.0, 1.0);
EmitVertex();
EndPrimitive();
}
This is how I create the destination cubemap and its framebuffer:
// Destination cube map creation
glGenTextures(1, &_destinationCubeMapTextureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, _destinationCubeMapTextureID);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
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);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (size_t face = 0; face < 6; face++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + (unsigned int)face, 0, GL_RGBA16F, 256, 256, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 8);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
// Destination depth map creation
glGenTextures(1, &_destinationDepthCubeMapTextureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, _destinationDepthCubeMapTextureID);
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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (size_t face = 0; face < 6; face++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + (unsigned int)face, 0, GL_DEPTH_COMPONENT24, 256, 256, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
// Destination framebuffer creation
glGenFramebuffers(1, &_destinationFrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _destinationFrameBuffer);
glFramebufferTexture(GL_FRAMEBUFFER, attachment, _destinationCubeMapTextureID, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _destinationDepthCubeMapTextureID, 0);
glDrawBuffers(1, &drawBuffer);
This is basically how I bind the cubemap framebuffer to draw and how I send the draw command:
void BindTextureTarget()
{
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _destinationFrameBuffer);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _destinationCubeMapTextureID, 0);
glViewport(0, 0, 256, 256);
}
...
glUseProgram(programID);
BindTextureTarget();
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 0.0);
pointVertexArray.Enable();
glDrawArrays(GL_POINTS, 0, 1);