So I’ve been implementing a deferred shader and I’ve run into some troubles trying to get a skybox working. My idea here is that after a HDR/Bloom pass to calculate the final picture I render it using a forward shader using a full screen quad. After this I’m trying to render a skybox but I can’t get it to work. Almost all online sources usually blit the depth buffer from the geometry pass into the main FBO, however after failing to do so and getting GL_INVALID_OPERATION errors and after asking on stackoverflow it seems that the default framebuffer is user defined and that’s what causing my errors. So Instead I’ve been using the stored depth texture from the geometry pass which I’m trying to use to determine if a fragment should have the skybox rendered to it. Essentially I draw the final image to a full screen quad like this
ShaderMan.bindShader(FINAL_BLUR_SHADER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//Enables the depth texture to be written into
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniform1i(ShaderMan.getActiveShader().getUniformLocation("hdrTexture"), 0);
glUniform1i(ShaderMan.getActiveShader().getUniformLocation("bloomTexture"), 1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mHDRTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, pingpongTextures[!horizontal]);
glBindVertexArray(mQuadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
ShaderMan.unbindShader();
Which works fine, and looks like this:
[ATTACH=CONFIG]1300[/ATTACH]
This should mean that the quad’s depth value is almost 0, or mapped to the near plane in [0,1] coordinates
Now after this I want to render the skybox and check if the stored depth value in the texture is 0, then I should render the skybox on that fragment. Now if I after the geometry pass just try to render the skybox wherever a depth of 0 is detected using these shaders:
VS
#version 430
layout (location = 0) in vec3 position;
//3D cubemap
out vec3 v2fTexcoords;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
void main()
{
//Trick the depth test since w/w will be 1 so it's always at max depth value
vec4 pos = projectionMatrix * viewMatrix * vec4(position, 1.0);
pos = pos*-1.0f;
gl_Position = pos.xyww;
v2fTexcoords = position;
}
FS
#version 430
in vec3 v2fTexcoords;
out vec4 fragColor;
uniform samplerCube skybox;
uniform sampler2D depthTexture;
uniform vec2 screenSize;
vec2 CalcTexCoord()
{
return gl_FragCoord.xy / screenSize;
}
void main()
{
vec2 TexCoord = CalcTexCoord();
float depthValue = texture2D(depthTexture,TexCoord).r;
if(depthValue == 0)
fragColor = texture(skybox, v2fTexcoords);
}
I get this image, as expected, also the pos*-1.0f was to change the direction of the textures since they were the wrong way at first, since z is set to w it should still map to 1 after w/w
[ATTACH=CONFIG]1301[/ATTACH]
Now, as I can clearly render the final image to a full screen quad and I can render the skybox and check if the depth value is 0 and then render the texture on that fragment everything should be fine right? Well no, I can’t get the skybox to render and I’m not sure where I’m doing something wrong, here’s the complete code for rendering the quad and then the skybox at the same time, which just results with the quad being drawn
ShaderMan.bindShader(FINAL_BLUR_SHADER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//Enables the depth texture to be written into
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniform1i(ShaderMan.getActiveShader().getUniformLocation("hdrTexture"), 0);
glUniform1i(ShaderMan.getActiveShader().getUniformLocation("bloomTexture"), 1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mHDRTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, pingpongTextures[!horizontal]);
glBindVertexArray(mQuadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
ShaderMan.unbindShader();
drawSkybox();
And the drawSkyBox() function
glDepthFunc(GL_LEQUAL);
ShaderMan.bindShader(SKY_BOX_SHADER);
glm::mat4 view = glm::mat4(glm::mat3(CameraMan.getActiveCamera()->getViewMatrix())); // Remove any translation component of the view matrix
glm::mat4 projection = CameraMan.getActiveCamera()->getProjectionMatrix();
glUniformMatrix4fv(ShaderMan.getActiveShader().getUniformLocation("viewMatrix"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(ShaderMan.getActiveShader().getUniformLocation("projectionMatrix"), 1, GL_FALSE, glm::value_ptr(projection));
// skybox cube
glUniform1i(ShaderMan.getActiveShader().getUniformLocation("skybox"), 0);
glUniform1i(ShaderMan.getActiveShader().getUniformLocation("depthTexture"), 1);
glUniform2f(ShaderMan.getActiveShader().getUniformLocation("screenSize"), mWindowWidth, mWindowHeight);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, mStoredDepthTexture);
mSkybox.render();
glDepthFunc(GL_LESS); // Set depth function back to default
ShaderMan.unbindShader();
I’ve tried setting the depthfunc to always pass in the skybox pass dut I still cant get it right.