diff --git a/modules/gfx/src/impl/scene_fx.cc b/modules/gfx/src/impl/scene_fx.cc index 6c4dfb3083b1c022e855fd6cc62aebfc1cbd8311..9e32dc329a8978e3859483e92fe5867317cba4f4 100644 --- a/modules/gfx/src/impl/scene_fx.cc +++ b/modules/gfx/src/impl/scene_fx.cc @@ -42,6 +42,7 @@ SceneFX::SceneFX(): scene_tex2_id_(), norm_tex2_id_(), scene_fb_(), + scene_rb_(), depth_rb_(), use_fb_(false) {} @@ -63,6 +64,7 @@ void SceneFX::Setup() glGenTextures(1,&kernel2_tex_id_); glGenFramebuffers(1,&scene_fb_); + glGenRenderbuffers(1,&scene_rb_); glGenRenderbuffers(1,&depth_rb_); glGenTextures(1,&scene_tex2_id_); glGenTextures(1,&norm_tex2_id_); @@ -208,7 +210,7 @@ void SceneFX::Postprocess() if(!shadow_flag && !amb_occl_flag && !depth_dark_flag) { // no postprocessing is needed - //return; + return; } Viewport vp=Scene::Instance().GetViewport(); @@ -255,14 +257,16 @@ void SceneFX::Postprocess() glUniform1i(glGetUniformLocation(cpr,"scene_map"),0); glUniform1i(glGetUniformLocation(cpr,"depth_map"),1); - glUniform2f(glGetUniformLocation(cpr,"i_vp"),1.0/static_cast<float>(vp.width),1.0/static_cast<float>(vp.height)); - double pm[16]; - glGetDoublev(GL_PROJECTION_MATRIX,pm); - glUniform4f(glGetUniformLocation(cpr,"abcd"),pm[0],pm[5],pm[10],pm[14]); if(shadow_flag) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,shadow_tex_id_); + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + // make explicit object instead of temporary to avoid potential crash with Data() + geom::Mat4 ttmp=Transpose(shadow_tex_mat_); + glLoadMatrix(ttmp.Data()); + glMatrixMode(GL_MODELVIEW); glActiveTexture(GL_TEXTURE0); glUniform1i(glGetUniformLocation(cpr,"shadow_flag"),1); glUniform1i(glGetUniformLocation(cpr,"shadow_map"),2); @@ -270,12 +274,6 @@ void SceneFX::Postprocess() glUniform1f(glGetUniformLocation(cpr,"shadow_epsilon"),0.002); glUniform1f(glGetUniformLocation(cpr,"shadow_multiplier"),0.4); - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - // make explicit object instead of temporary to avoid potential crash with Data() - geom::Mat4 ttmp=Transpose(shadow_tex_mat_); - glLoadMatrix(ttmp.Data()); - glMatrixMode(GL_MODELVIEW); } else { glUniform1i(glGetUniformLocation(cpr,"shadow_flag"),0); } @@ -304,9 +302,11 @@ void SceneFX::Postprocess() draw_screen_quad(vp.width,vp.height); if(shadow_flag) { + glActiveTexture(GL_TEXTURE2); glMatrixMode(GL_TEXTURE); glPopMatrix(); glMatrixMode(GL_MODELVIEW); + glActiveTexture(GL_TEXTURE0); } glDisable(GL_TEXTURE_1D); @@ -328,11 +328,30 @@ void SceneFX::DrawTex(unsigned int w, unsigned int h, GLuint texid) void SceneFX::prep_shadow_map() { - GLint smap_size=256 << shadow_quality; + GLint smap_size=256 * (1+shadow_quality); + +#if 1 + glBindFramebuffer(GL_FRAMEBUFFER, scene_fb_); + + glBindRenderbuffer(GL_RENDERBUFFER, scene_rb_); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA,smap_size,smap_size); + glBindRenderbuffer(GL_RENDERBUFFER, depth_rb_); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,smap_size,smap_size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, scene_rb_); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rb_); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if(status!=GL_FRAMEBUFFER_COMPLETE) { + LOGN_DEBUG("fbo switch for shadow mapping failed, using fallback"); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } +#endif // modelview transform for the lightsource pov mol::Transform ltrans(Scene::Instance().GetTransform()); - ltrans.SetRot(Scene::Instance().GetLightRot()*Scene::Instance().GetTransform().GetRot()); + ltrans.SetRot(Scene::Instance().GetLightRot()*ltrans.GetRot()); // calculate encompassing box for ortho projection geom::AlignedCuboid bb=Scene::Instance().GetBoundingBox(ltrans); @@ -384,12 +403,26 @@ void SceneFX::prep_shadow_map() glPopAttrib(); //glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); +#if 1 + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + // set up appropriate texture matrix geom::Mat4 bias(0.5,0.0,0.0,0.5, 0.0,0.5,0.0,0.5, 0.0,0.0,0.5,0.5, 0.0,0.0,0.0,1.0); - shadow_tex_mat_ = bias*pmat*ltrans.GetMatrix(); + //shadow_tex_mat_ = bias*pmat*ltrans.GetMatrix(); + Scene::Instance().ResetProjection(); + glGetv(GL_PROJECTION_MATRIX, glpmat); + geom::Mat4 pmat2(Transpose(geom::Mat4(glpmat))); + /* + given the normalized coordinates in scenefx, the camera projection and modelview transformation + are first reverted, and then the light modelview and projection are applied, resulting (with the + bias) in the proper 2D lookup into the shadow map + */ + shadow_tex_mat_ = bias*pmat*ltrans.GetMatrix()*geom::Invert(Scene::Instance().GetTransform().GetMatrix())*geom::Invert(pmat2); } void SceneFX::prep_amb_occlusion() @@ -482,6 +515,8 @@ void SceneFX::draw_screen_quad(unsigned int w, unsigned int h) glPushMatrix(); glLoadIdentity(); glEnable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); // draw glColor3f(1.0,0.0,1.0); glBegin(GL_QUADS); diff --git a/modules/gfx/src/impl/scene_fx.hh b/modules/gfx/src/impl/scene_fx.hh index ebd4ae6e7c97131408af38d3db200974fdc73fe3..3048e1d52dbdcf30980a2a61c5619909acd5f3e0 100644 --- a/modules/gfx/src/impl/scene_fx.hh +++ b/modules/gfx/src/impl/scene_fx.hh @@ -82,6 +82,7 @@ private: GLuint scene_tex2_id_; GLuint norm_tex2_id_; GLuint scene_fb_; + GLuint scene_rb_; GLuint depth_rb_; bool use_fb_; diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc index 38aaaff76d781d76cca6eb6d5f7780415109fb27..c1145759789eefdc2cb5ff8f4152ea749a7dbd29 100644 --- a/modules/gfx/src/scene.cc +++ b/modules/gfx/src/scene.cc @@ -181,7 +181,7 @@ bool Scene::GetShadow() const void Scene::SetShadowQuality(int q) { #if OST_SHADER_SUPPORT_ENABLED - impl::SceneFX::Instance().shadow_quality=std::min(3,std::max(0,q)); + impl::SceneFX::Instance().shadow_quality=std::min(8,std::max(0,q)); RequestRedraw(); #endif } diff --git a/modules/gfx/src/shader/scenefx_fs.glsl b/modules/gfx/src/shader/scenefx_fs.glsl index 2c7341de096e8f03c23075cb1046135c59a1a68c..e8acfcefcca8289305183381e403b1999efbce5c 100644 --- a/modules/gfx/src/shader/scenefx_fs.glsl +++ b/modules/gfx/src/shader/scenefx_fs.glsl @@ -1,7 +1,5 @@ uniform sampler2D scene_map; uniform sampler2D depth_map; -uniform vec2 i_vp; -uniform vec4 abcd; uniform bool shadow_flag; uniform sampler2D shadow_map; uniform float shadow_depth_bias; @@ -14,13 +12,6 @@ uniform bool dark_flag; uniform sampler2D dark_map; uniform float dark_mult; -vec3 unproject(in vec3 scr) -{ - vec3 tmp=vec3(scr.x*i_vp.x*2.0-1.0,scr.y*i_vp.y*2.0-1.0,scr.z); - float iw = 1.0/(tmp.z/abcd.w+abcd.z/abcd.w); - return iw*vec3(tmp.x/abcd.x,tmp.y/abcd.y,-1.0); -} - float CalcShadowFactor(in vec4 coord, in vec2 o) { // get original depth value of line projected towards light @@ -30,15 +21,21 @@ float CalcShadowFactor(in vec4 coord, in vec2 o) void main() { + float depth = texture2D(depth_map,gl_TexCoord[0].xy).r; + if(depth>=1.0) { + discard; + } vec4 scene_color=texture2D(scene_map,gl_TexCoord[0].xy); gl_FragColor.a = scene_color.a; float shadow_factor=1.0; if(shadow_flag) { - float depth = texture2D(depth_map,gl_TexCoord[0].xy).r; - vec4 tcoord = gl_ModelViewProjectionMatrixInverse*vec4(gl_FragCoord.xy*i_vp*2.0-1.0,depth,1.0); - vec4 coord = gl_TextureMatrix[0]*tcoord; + vec4 pcoord = vec4(gl_TexCoord[0].xy*2.0-1.0,depth*2.0-1.0,1.0); + vec4 coord = gl_TextureMatrix[2]*pcoord; coord/=coord.w; + //float d = texture2D(shadow_map, coord.xy).r; + //gl_FragColor.rgb=vec3(1.0,d,0.0); + //return; shadow_factor = 0.0; shadow_factor += 0.18*CalcShadowFactor(coord, vec2(-0.7, -0.7)); shadow_factor += 0.18*CalcShadowFactor(coord, vec2(0.7, -0.7));