c++ - Deferred Rendering Skybox OpenGL -
i've implemented deferred rendering , having trouble getting skybox working. try rendering skybox @ end of rendering loop , black screen. here's rendering loop:
//binds fbo gbuffer.bind(); //the shader writes info gbuffer geometrypass.bind(); gldepthmask(gl_true); glclear(gl_color_buffer_bit | gl_depth_buffer_bit); glenable(gl_depth_test); gldisable(gl_blend); //draw geometry geometrypass.setuniform("model", transform.getmodel()); geometrypass.setuniform("mvp", camera.getviewprojection() * transform.getmodel()); mesh3.draw(); geometrypass.setuniform("model", transform2.getmodel()); geometrypass.setuniform("mvp", camera.getviewprojection() * transform2.getmodel()); sphere.draw(); gldepthmask(gl_false); gldisable(gl_depth_test); glenable(gl_blend); glblendequation(gl_func_add); glblendfunc(gl_one, gl_one); glbindframebuffer(gl_framebuffer, 0); glclear(gl_color_buffer_bit); //shader calculates lighting pointlightpass.bind(); pointlightpass.setuniform("camerapos", camera.gettransform().getposition()); (int = 0; < 2; i++) { pointlightpass.setuniformpointlight("light", pointlights[i]); pointlightpass.setuniform("mvp", glm::mat4(1.0f)); //skybox.getcubemap()->bind(9); quad.draw(); } //draw skybox glenable(gl_depth_test); skybox.render(camera); window.update(); window.swapbuffers();
the following skybox's render function
glcullface(gl_front); gldepthfunc(gl_lequal); m_transform.setposition(camera.gettransform().getposition()); m_shader->bind(); m_shader->setuniform("mvp", camera.getviewprojection() * m_transform.getmodel()); m_shader->setuniform("cubemap", 0); m_cubemap->bind(0); m_cubemesh->draw(); gldepthfunc(gl_less); glcullface(gl_back);
and here skybox's vertex shader:
layout (location = 0) in vec3 position; out vec3 texcoord; uniform mat4 mvp; void main() { vec4 pos = mvp * vec4(position, 1.0); gl_position = pos.xyww; texcoord = position; }
the skybox's fragment shader sets output color texture(cubemap, texcoord)
. can see vertex shader, i'm setting position's z
component w
have depth of 1. setting depth function gl_lequal
fail depth test. should not draw skybox in places other objects weren't drawn? why result in black screen?
i know have set skybox correctly because if draw skybox shows fine.
i can briefly see split second geometry should drawn before skybox drawn on top of everything.
since you're using double buffering, seeing different things must due different frame being drawn. depth buffer in default framebuffer isn't being cleared, believe cause of temporal instability @ least.
in case, want default depth buffer same gbuffer when draw skybox. quick way achieve glblitframebuffer, avoiding need clear it:
glbindframebuffer(gl_read_framebuffer, gbuffer); glbindframebuffer(gl_draw_framebuffer, 0); glblitframebuffer(..., gl_depth_buffer_bit, ...);
now explain black screen when skybox fills screen. without depth test, of course skybox draws. depth test, skybox still draws on first frame, shortly after second frame clears colour buffer. depth buffer still contains stale skybox values not re-draw frame , you're left black...
however geometry pass draws without depth testing enabled, should still visible if skybox isn't. happen gl_less
, have gl_lequal
. and have gldepthmask
false, means nothing should write default depth buffer in code. points depth buffer containing other values, perhaps uninitialized, in experience it's zero. still happens when skybox doesn't fill screen, drawn cube away camera, blows away argument. now, perhaps if geometry failed draw in second frame explain it. matter blatant driver bugs too, i'm not seeing problems in given code.
tldr: many unexplained things, **i tried myself , can't reproduce problem...
here's quick example based on code , works fine me...
(green sphere geometry, red cube skybox)
gl_position = pos
:
note yellow additive blending if skybox drawn on top. have thought you'd seeing too.
gl_position = pos.xyww
:
now code...
//i haven't enabled face culling, shouldn't affect //binds fbo fbo.bind(); //the shader writes info gbuffer //geometrypass.bind(); //fixed pipeline gldepthmask(gl_true); glclear(gl_color_buffer_bit | gl_depth_buffer_bit); glenable(gl_depth_test); gldisable(gl_blend); glcolor3f(0,1,0); fly.uploadcamera(); //glloadmatrixf sphere.draw(); gldepthmask(gl_false); gldisable(gl_depth_test); glenable(gl_blend); glblendequation(gl_func_add); glblendfunc(gl_one, gl_one); fbo.unbind(); //glbindframebuffer(gl_framebuffer, 0); glclear(gl_color_buffer_bit); //shader calculates lighting drawtex.use(); //pointlightpass.setuniform("camerapos", camera.gettransform().getposition()); drawtex.set("tex", *(texture2d*)fbo.colour[0]); (int = 0; < 2; i++) { //pointlightpass.setuniformpointlight("light", pointlights[i]); //pointlightpass.setuniform("mvp", glm::mat4(1.0f)); //skybox.getcubemap()->bind(9); drawtex.set("modelviewmat", mat44::identity()); quad.draw(); } drawtex.unuse(); //draw skybox glenable(gl_depth_test); glbindframebuffer(gl_read_framebuffer, fbo); glbindframebuffer(gl_draw_framebuffer, 0); glblitframebuffer(0, 0, fbo.size.x, fbo.size.y, 0, 0, fbo.size.x, fbo.size.y, gl_depth_buffer_bit, gl_nearest); glbindframebuffer(gl_framebuffer, 0); //glcullface(gl_front); gldepthfunc(gl_lequal); //m_transform.setposition(camera.gettransform().getposition()); skybox.use(); skybox.set("mvp", fly.camera.getprojection() * fly.camera.getinverse() * mat44::translate(1,0,0)); //m_shader->setuniform("mvp", camera.getviewprojection() * m_transform.getmodel()); //m_shader->setuniform("cubemap", 0); //m_cubemap->bind(0); cube.draw(); skybox.unuse(); gldepthfunc(gl_less); //glcullface(gl_back); //window.update(); //window.swapbuffers();
Comments
Post a Comment