Here is a a minimal example causing GL to render a black screen:
// ... all the usual GL init code etc. & GLAM includes
const int SHADOW_SIZE = 1024;
const int SWIDTH = 1200, SHEIGHT = 900;
unsigned int shadowMap, albedoSpec;
// Begin snip 1
glGenTextures(1, &shadowMap);
glBindTexture(GL_TEXTURE_CUBE_MAP, shadowMap);
for (unsigned int i = 0; i < 6; ++i)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, SHADOW_SIZE, SHADOW_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
// End snip 1
glGenTextures(1, &gAlbedoSpec);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SWIDTH, SHEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
// ... some time later, in the draw loop
// The active shader is called `shader`
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
// sets the `uniform sampler2D gAlbedoSpec` to use texture unit `0`
shader.setInt("gAlbedoSpec", 0);
// ... code which draws the scene using `shader`
Now, in my shader I have something like this:
uniform sampler2D gAlbedoSpec;
uniform samplerCube shadowMap;
// ... some code which uses gAlbedoSpec
if (valueWhichIsFalseInThisExample) {
// ... some code which uses shadowMap
}
If I remove the bit of code marked snip 1, then GL will render whatever I tell it to. Otherwise, the screen will be black without exception. To me it seems that the act of simply generating a cubemap has lead to GL to refuse to render. So, my question is, why does generating a cubemap lead GL to refuse to render anything to the screen?
(This is all the relevant code and does minimally reproduce the problem.)
When will OpenGL refuse to render?
Per the wiki, if both
GL_TEXTURE_2DandGL_TEXTURE_CUBE) are bound to the same image unit (e.g.GL_TEXTURE0); and,sampler2DandsamplerCube) are both set to use this image unit,then no rendering will be performed (leading to a black screen).
Satisfying the first criterion
In creating a cubemap during instantiation of a point light, I was binding it to the active texture unit, which happened to be
GL_TEXTURE0:Later, when it came to rendering the gBuffer, I was binding the albedo/specular buffer also to
GL_TEXTURE0, this time explicitly as:Thus criterion 1 of the above has now been fulfilled.
Satisfying the second criterion
I also set a relevant uniform for the fragment shader so that I could sample the albedo/specular buffer:
In the shader, this uniform is defined as
In the same shader, at some point I have something along the lines of
This never has a value explicitly set, since I disabled shadow-casting for the point light, but its default value is
0, and this is enough to fulfil criterion 2 of the above.Conclusion and solution
Thus, I had accidentally managed to set up a situation where I caused OpenGL to refuse to render. It didn't matter that I never actually accessed the second uniform, simply having it set was enough to cause problems.
The best solution is probably to make sure that the cubemap is unbound once we are finished with it during point light instantiation: