diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc index 5a1a2057f0ddfdb7a4edbe4d1e855079df9fba61..f5658f464db25b7661aa0d3e1695d35186c62895 100644 --- a/modules/gfx/pymod/export_scene.cc +++ b/modules/gfx/pymod/export_scene.cc @@ -118,6 +118,7 @@ void export_Scene() .def("SetShadow",&Scene::SetShadow) .def("SetShadowQuality",&Scene::SetShadowQuality) .def("SetDepthDarkening",&Scene::SetDepthDarkening) + .def("SetAmbientOcclusion",&Scene::SetAmbientOcclusion) .def("AttachObserver",&Scene::AttachObserver) .def("StartOffscreenMode",&Scene::StartOffscreenMode) .def("StopOffscreenMode",&Scene::StopOffscreenMode) diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt index 1e17c9008ebd4a3711bc1302735237528d28df59..b5667bc33ba68cd156e95e088c62a3432e3805bb 100644 --- a/modules/gfx/src/CMakeLists.txt +++ b/modules/gfx/src/CMakeLists.txt @@ -244,7 +244,8 @@ if (USE_SHADER) shader/outline_vs.glsl shader/quadpp_vs.glsl shader/convolute1_fs.glsl - shader/amboccl_fs.glsl + shader/scenefx_vs.glsl + shader/scenefx_fs.glsl ) copy_if_different("./" "${SHARED_DATA_PATH}/shader" "${SHADER_FILES}" "SHADER_TARGETS" ost_gfx) diff --git a/modules/gfx/src/impl/scene_fx.cc b/modules/gfx/src/impl/scene_fx.cc index 7e6d8033f1521e0b37273c3a4d03bdb0502185b7..413ef43f9d6840bf1d7daadfe4165158b5e40f96 100644 --- a/modules/gfx/src/impl/scene_fx.cc +++ b/modules/gfx/src/impl/scene_fx.cc @@ -1,29 +1,213 @@ #include "scene_fx.hh" +#include <ost/log.hh> + #include <ost/gfx/gfx_node.hh> #include <ost/gfx/shader.hh> #include <ost/gfx/scene.hh> namespace ost { namespace gfx { namespace impl { -void prep_shadow_map(Scene& scene, GLuint texunit, GLuint texid, uint quality) +SceneFX& SceneFX::Instance() +{ + static SceneFX inst; + return inst; +} + +SceneFX::SceneFX(): + shadow_flag(false), + shadow_quality(1), + depth_dark_flag(false), + amb_occl_flag(false), + scene_tex_id_(), + depth_tex_id_(), + shadow_tex_id_(), + occl_tex_id_(), + dark_tex_id_(), + norm_tex_id_(), + scene_tex2_id_(), + norm_tex2_id_(), + scene_fb_(), + depth_rb_(), + use_fb_(false) +{} + +SceneFX::~SceneFX() +{} + +void SceneFX::Setup() +{ + glGenTextures(1,&scene_tex_id_); + glGenTextures(1,&depth_tex_id_); + glGenTextures(1,&shadow_tex_id_); + glGenTextures(1,&occl_tex_id_); + glGenTextures(1,&dark_tex_id_); + glGenTextures(1,&norm_tex_id_); + + glGenFramebuffers(1,&scene_fb_); + glGenRenderbuffers(1,&depth_rb_); + glGenTextures(1,&scene_tex2_id_); + glGenTextures(1,&norm_tex2_id_); + + glActiveTexture(GL_TEXTURE0); + + glBindTexture(GL_TEXTURE_2D, scene_tex_id_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + glBindTexture(GL_TEXTURE_2D, depth_tex_id_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + glBindTexture(GL_TEXTURE_2D, shadow_tex_id_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + glBindTexture(GL_TEXTURE_2D, occl_tex_id_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + glBindTexture(GL_TEXTURE_2D, dark_tex_id_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + glBindTexture(GL_TEXTURE_2D, norm_tex_id_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + +} + +void SceneFX::Resize(unsigned int w, unsigned int h) +{ + glBindTexture(GL_TEXTURE_2D, scene_tex2_id_); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glBindTexture(GL_TEXTURE_2D, norm_tex2_id_); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, scene_fb_); + + glBindRenderbuffer(GL_RENDERBUFFER, depth_rb_); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,w,h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rb_); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, scene_tex2_id_, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, norm_tex2_id_, 0); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if(status!=GL_FRAMEBUFFER_COMPLETE) { + use_fb_=false; + LOGN_VERBOSE("framebuffer error code " << status); + } else { + use_fb_=true; + } + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void SceneFX::Preprocess() +{ + if(use_fb_) { + glBindFramebuffer(GL_FRAMEBUFFER, scene_fb_); + } +} + +void SceneFX::Postprocess() { - GLint smap_size=256 << quality; + Viewport vp=Scene::Instance().GetViewport(); + // grab color buffer + glBindTexture(GL_TEXTURE_2D, scene_tex_id_); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vp.x, vp.y, vp.width, vp.height, 0); + // and depth buffer + glBindTexture(GL_TEXTURE_2D, depth_tex_id_); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, vp.x, vp.y, vp.width, vp.height, 0); + + if(use_fb_) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + if(shadow_flag) { + prep_shadow_map(); + } + if(amb_occl_flag) { + //prep_amb_occlusion(); + //draw_debug_tex(vp.width,vp.height,norm_tex_id_); + } + if(depth_dark_flag) { + //prep_depth_darkening(); + } + + + Shader::Instance().PushProgram(); + glEnable(GL_TEXTURE_2D); + Shader::Instance().Activate("scenefx"); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,depth_tex_id_); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,scene_tex_id_); + GLuint cpr=Shader::Instance().GetCurrentProgram(); + glUniform1i(glGetUniformLocation(cpr,"scene"),0); + glUniform1i(glGetUniformLocation(cpr,"depth"),1); + glUniform2f(glGetUniformLocation(cpr,"scalef"), + 1.0f/static_cast<float>(vp.width), + 1.0f/static_cast<float>(vp.height)); + glUniform2f(glGetUniformLocation(cpr,"zmorph"), + Scene::Instance().GetFar()-Scene::Instance().GetNear(), + Scene::Instance().GetNear()); + + if(shadow_flag) { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,shadow_tex_id_); + glUniform1i(glGetUniformLocation(cpr,"shadow_flag"),1); + glUniform1i(glGetUniformLocation(cpr,"shadow_map"),2); + glUniform1f(glGetUniformLocation(cpr,"shadow_depth_bias"),0.008); + glUniform1f(glGetUniformLocation(cpr,"shadow_epsilon"),0.002); + glUniform1f(glGetUniformLocation(cpr,"shadow_multiplier"),0.4); + } else { + glUniform1i(glGetUniformLocation(cpr,"shadow_flag"),0); + } +#if 0 + if(amb_occl_flag) { + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D,occl_tex_id_); + glUniform1i(glGetUniformLocation(cpr,"occl_flag"),1); + glUniform1i(glGetUniformLocation(cpr,"occl_map"),3); + } else { + glUniform1i(glGetUniformLocation(cpr,"occl_flag"),0); + } +#endif + + draw_screen_quad(vp.width,vp.height); + glDisable(GL_TEXTURE_2D); + Shader::Instance().PopProgram(); +} + +void SceneFX::prep_shadow_map() +{ + GLint smap_size=256 << shadow_quality; // modelview transform for the lightsource pov - mol::Transform ltrans(scene.GetTransform()); - ltrans.SetRot(scene.GetLightRot()*scene.GetTransform().GetRot()); + mol::Transform ltrans(Scene::Instance().GetTransform()); + ltrans.SetRot(Scene::Instance().GetLightRot()*Scene::Instance().GetTransform().GetRot()); // calculate encompassing box for ortho projection - geom::AlignedCuboid bb=scene.GetBoundingBox(ltrans); + geom::AlignedCuboid bb=Scene::Instance().GetBoundingBox(ltrans); geom::Vec3 tmin=bb.GetMin(); geom::Vec3 tmax=bb.GetMax(); - // render pass 1 - without shadows - - // turn shadowing off for subsequent rendering - Shader::Instance().SetShadowMapping(false,0); - // save overall gl settings glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // maximize rendering for depth-only information @@ -53,26 +237,12 @@ void prep_shadow_map(Scene& scene, GLuint texunit, GLuint texid, uint quality) glMultMatrix(ltrans.GetTransposedMatrix().Data()); // only render non-transparent objects for the shadow map - scene.GetRootNode()->RenderGL(DEPTH_RENDER_PASS); + Scene::Instance().GetRootNode()->RenderGL(DEPTH_RENDER_PASS); // now get the shadow map - glActiveTexture(GL_TEXTURE0+texunit); - glBindTexture(GL_TEXTURE_2D, texid); - - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, - 0,0, smap_size,smap_size, 0); - - // all of the following texture and shader params need to be moved - // to a one-time initialization place - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - - // assign tex unit 0 to shadow map - Shader::Instance().SetShadowMapping(true,texunit); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, shadow_tex_id_); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0,0, smap_size,smap_size, 0); // restore settings glPopMatrix(); @@ -83,8 +253,6 @@ void prep_shadow_map(Scene& scene, GLuint texunit, GLuint texid, uint quality) glPopAttrib(); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); - glEnable(GL_TEXTURE_2D); - // set up appropriate texture matrix geom::Mat4 bias(0.5,0.0,0.0,0.5, 0.0,0.5,0.0,0.5, @@ -100,78 +268,59 @@ void prep_shadow_map(Scene& scene, GLuint texunit, GLuint texid, uint quality) glMatrixMode(GL_MODELVIEW); } -void prep_amb_occlusion(Scene& scene, GLuint texunit, GLuint texid) +void SceneFX::prep_amb_occlusion() { + Viewport vp=Scene::Instance().GetViewport(); + + // kernel is static for now, inside the convolution shader + Shader::Instance().PushProgram(); + Shader::Instance().Activate("amboccl"); + GLuint cpr=Shader::Instance().GetCurrentProgram(); + // assign tex units + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,depth_tex_id_); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,norm_tex_id_); + glUniform1i(glGetUniformLocation(cpr,"depth"),0); + glUniform1i(glGetUniformLocation(cpr,"norm"),1); + + // set up viewport filling quad to run the fragment shader + draw_screen_quad(vp.width,vp.height); + + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, occl_tex_id_); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, 0,0, vp.width, vp.height, 0); + + Shader::Instance().PopProgram(); } -void prep_depth_darkening(Scene& scene, GLuint texunit, GLuint texid) +void SceneFX::prep_depth_darkening() { - Viewport vp=scene.GetViewport(); - prep_depth_map(scene,vp.width/2,vp.height/2,texunit,texid); + Viewport vp=Scene::Instance().GetViewport(); // kernel is static for now, inside the convolution shader - - // now convolute the depth map with the kernel Shader::Instance().PushProgram(); Shader::Instance().Activate("convolute1"); GLuint cpr=Shader::Instance().GetCurrentProgram(); // assign tex units + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,depth_tex_id_); glUniform1i(glGetUniformLocation(cpr,"data"),1); glUniform1i(glGetUniformLocation(cpr,"vp_width"),vp.width/2); glUniform1i(glGetUniformLocation(cpr,"vp_height"),vp.height/2); // set up viewport filling quad to run the fragment shader - draw_screen_quad(vp.width/2,vp.height/2,texunit, texid); - - Shader::Instance().PopProgram(); - - // mode 1, tex unit 1 - Shader::Instance().SetDepthMapping(1,texunit); -} - -void prep_depth_map(Scene& scene, unsigned int width, unsigned int height,GLuint texunit, GLuint texid) -{ - // render pass 1 - without shadows - Shader::Instance().SetShadowMapping(false,0); - // save overall gl settings - glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT); - // maximize rendering for depth-only information - glDisable(GL_LIGHTING); - glDisable(GL_FOG); - glDisable(GL_COLOR_MATERIAL); - glDisable(GL_NORMALIZE); - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); + draw_screen_quad(vp.width/2,vp.height/2); - // render scene with only depth components - glClear(GL_DEPTH_BUFFER_BIT); - glViewport(0,0,width,height); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glMultMatrix(scene.GetTransform().GetTransposedMatrix().Data()); - scene.GetRootNode()->RenderGL(DEPTH_RENDER_PASS); + glBindTexture(GL_TEXTURE_2D, dark_tex_id_); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0,0,vp.width/2, vp.height/2, 0); - // now get the depth map - glActiveTexture(texunit); - glBindTexture(GL_TEXTURE_2D, texid); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0,0, width, height, 0); - - // restore settings - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glPopAttrib(); - glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + Shader::Instance().PopProgram(); } -void draw_screen_quad(unsigned int w, unsigned int h, GLuint gltex, GLuint tex_id) +void SceneFX::draw_screen_quad(unsigned int w, unsigned int h) { - glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_FOG_BIT); + glPushAttrib(GL_ALL_ATTRIB_BITS); // setup glDisable(GL_DEPTH_TEST); @@ -182,7 +331,7 @@ void draw_screen_quad(unsigned int w, unsigned int h, GLuint gltex, GLuint tex_i glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); glDisable(GL_POINT_SMOOTH); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -191,7 +340,7 @@ void draw_screen_quad(unsigned int w, unsigned int h, GLuint gltex, GLuint tex_i glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - + glEnable(GL_TEXTURE_2D); // draw glColor3f(1.0,0.0,1.0); glBegin(GL_QUADS); @@ -205,16 +354,6 @@ void draw_screen_quad(unsigned int w, unsigned int h, GLuint gltex, GLuint tex_i glVertex2f(1.0,0.0); glEnd(); - // grab the result - glEnable(GL_TEXTURE_2D); - glActiveTexture(gltex); - glBindTexture(GL_TEXTURE_2D, tex_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0,0, w, h, 0); - // restore settings glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -224,7 +363,7 @@ void draw_screen_quad(unsigned int w, unsigned int h, GLuint gltex, GLuint tex_i } // this debug code draws the given texture across the complete screen -void draw_debug_tex(unsigned int w, unsigned int h, GLuint texid) +void SceneFX::draw_debug_tex(unsigned int w, unsigned int h, GLuint texid) { glPushAttrib(GL_ALL_ATTRIB_BITS); Shader::Instance().PushProgram(); diff --git a/modules/gfx/src/impl/scene_fx.hh b/modules/gfx/src/impl/scene_fx.hh index 5c407e8be1899f99ec99a810e58de347471422f1..6db023e03987e0fbe34ac41e51ef9cf3f2304619 100644 --- a/modules/gfx/src/impl/scene_fx.hh +++ b/modules/gfx/src/impl/scene_fx.hh @@ -33,12 +33,49 @@ class Scene; namespace impl { -void prep_shadow_map(Scene& scene, GLuint texunit, GLuint texid, uint quality); -void prep_depth_darkening(Scene& scene, GLuint texunit, GLuint texid); -void prep_amb_occlusion(Scene& scene, GLuint texunit, GLuint texid); -void prep_depth_map(Scene& scene, uint, uint, GLuint texunit, GLuint texid); -void draw_screen_quad(unsigned int w, unsigned int h, GLuint texunit, GLuint texid); -void draw_debug_tex(unsigned int w, unsigned int h, GLuint texid); +class SceneFX { +public: + ~SceneFX(); + static SceneFX& Instance(); + + void Setup(); + + void Resize(unsigned int w, unsigned int h); + + void Preprocess(); + // assumes scene has been drawn in the active framebuffer + void Postprocess(); + + bool shadow_flag; + int shadow_quality; + bool depth_dark_flag; + bool amb_occl_flag; + +private: + SceneFX(); + SceneFX(const SceneFX&) {} + SceneFX& operator=(const SceneFX&) {return *this;} + + void prep_shadow_map(); + void prep_depth_darkening(); + void prep_amb_occlusion(); + void draw_screen_quad(uint w, uint h); + void draw_debug_tex(unsigned int w, unsigned int h, GLuint texid); + + GLuint scene_tex_id_; + GLuint depth_tex_id_; + GLuint shadow_tex_id_; + GLuint occl_tex_id_; + GLuint dark_tex_id_; + GLuint norm_tex_id_; + + GLuint scene_tex2_id_; + GLuint norm_tex2_id_; + GLuint scene_fb_; + GLuint depth_rb_; + + bool use_fb_; +}; }}} // ns diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc index 5a8222295e22f6336f574ba2e526071706d0422d..6c8bbded8a36d710529892a2d4b33682600aefef 100644 --- a/modules/gfx/src/scene.cc +++ b/modules/gfx/src/scene.cc @@ -109,14 +109,6 @@ Scene::Scene(): axis_flag_(false), fog_flag_(true), fog_color_(0.0,0.0,0.0,0.0), - shadow_flag_(false), - shadow_quality_(1), - shadow_tex_id_(), - depth_dark_flag_(false), - amb_occl_flag_(false), - depth_tex_id_(), - kernel_tex_id_(), - scene_tex_id_(), auto_autoslab_(true), offscreen_flag_(false), main_offscreen_buffer_(0), @@ -168,34 +160,46 @@ Color Scene::GetFogColor() const void Scene::SetShadow(bool f) { - shadow_flag_=f; +#if OST_SHADER_SUPPORT_ENABLED + impl::SceneFX::Instance().shadow_flag=f; // the redraw routine will deal with the Shader RequestRedraw(); +#endif +} + +bool Scene::GetShadow() const +{ +#if OST_SHADER_SUPPORT_ENABLED + return impl::SceneFX::Instance().shadow_flag; +#endif } void Scene::SetShadowQuality(int q) { - shadow_quality_=std::min(3,std::max(0,q)); - if(shadow_flag_) { - RequestRedraw(); - } +#if OST_SHADER_SUPPORT_ENABLED + impl::SceneFX::Instance().shadow_quality=std::min(3,std::max(0,q)); + RequestRedraw(); +#endif } void Scene::SetDepthDarkening(bool f) { - depth_dark_flag_=f; +#if OST_SHADER_SUPPORT_ENABLED + impl::SceneFX::Instance().depth_dark_flag=f; // the redraw routine will deal with the Shader RequestRedraw(); +#endif } void Scene::SetAmbientOcclusion(bool f) { - amb_occl_flag_=f; +#if OST_SHADER_SUPPORT_ENABLED + impl::SceneFX::Instance().amb_occl_flag=f; // the redraw routine will deal with the Shader RequestRedraw(); +#endif } - void Scene::SetShadingMode(const std::string& smode) { #if OST_SHADER_SUPPORT_ENABLED @@ -320,11 +324,8 @@ void Scene::InitGL() LOGN_DEBUG("scene: shader setup"); Shader::Instance().Setup(); SetShadingMode("default"); - - glGenTextures(1,&shadow_tex_id_); - glGenTextures(1,&depth_tex_id_); - glGenTextures(1,&kernel_tex_id_); - glGenTextures(1,&scene_tex_id_); + LOGN_DEBUG("scene: scenefx setup"); + impl::SceneFX::Instance().Setup(); #endif prep_glyphs(); @@ -369,6 +370,9 @@ void Scene::SetViewport(int w, int h) vp_height_=h; aspect_ratio_=static_cast<float>(w)/static_cast<float>(h); ResetProjection(); +#if OST_SHADER_SUPPORT_ENABLED + impl::SceneFX::Instance().Resize(w,h); +#endif } void Scene::Resize(int w, int h) @@ -506,23 +510,6 @@ void Scene::RenderGL() { if(auto_autoslab_) Autoslab(false, false); - #if OST_SHADER_SUPPORT_ENABLED - if(amb_occl_flag_) { - impl::prep_amb_occlusion(*this,GL_TEXTURE1, depth_tex_id_); - } else { - Shader::Instance().SetOcclusionMapping(0,0); - } - if(depth_dark_flag_) { - impl::prep_depth_darkening(*this,GL_TEXTURE1, depth_tex_id_); - } else { - Shader::Instance().SetDepthMapping(0,0); - } - if(shadow_flag_) { - impl::prep_shadow_map(*this,GL_TEXTURE0,shadow_tex_id_,shadow_quality_); - } else { - Shader::Instance().SetShadowMapping(0,0); - } - #endif glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); prep_blur(); @@ -533,6 +520,17 @@ void Scene::RenderGL() glMultMatrix(transform_.GetTransposedMatrix().Data()); + // TODO: handle stereo +#if OST_SHADER_SUPPORT_ENABLED + impl::SceneFX::Instance().Preprocess(); +#endif + render_standard_scene(); +#if OST_SHADER_SUPPORT_ENABLED + impl::SceneFX::Instance().Postprocess(); +#endif + render_glow(); + +#if 0 if(stereo_==2 || stereo_==3) { render_interlaced_stereo(); } else if (stereo_==1) { @@ -540,11 +538,8 @@ void Scene::RenderGL() } else { this->render_scene_with_glow(); } - #if OST_SHADER_SUPPORT_ENABLED - if(shadow_flag_) { - glDisable(GL_TEXTURE_2D); - } - #endif +#endif + } void Scene::Register(GLWinBase* win) @@ -1681,7 +1676,7 @@ void Scene::prep_blur() glFlush(); } -void Scene::render_scene_with_glow() +void Scene::render_standard_scene() { glDepthFunc(GL_LEQUAL); glDepthMask(1); @@ -1693,8 +1688,11 @@ void Scene::render_scene_with_glow() root_node_->RenderGL(TRANSPARENT_RENDER_PASS); glDisable(GL_BLEND); root_node_->RenderGL(OVERLAY_RENDER_PASS); +} - glPushAttrib(GL_ENABLE_BIT); +void Scene::render_glow() +{ + glPushAttrib(GL_ALL_ATTRIB_BITS); glEnable(GL_COLOR_MATERIAL); glShadeModel(GL_FLAT); glDisable(GL_FOG); @@ -1739,6 +1737,7 @@ void Scene::stereo_projection(unsigned int view) void Scene::render_interlaced_stereo() { +#if 0 // set up stencil buffer glPushAttrib(GL_STENCIL_BUFFER_BIT| GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT); glMatrixMode(GL_PROJECTION); @@ -1791,10 +1790,12 @@ void Scene::render_interlaced_stereo() root_node_->RenderGL(GLOW_RENDER_PASS); glDisable(GL_STENCIL_TEST); glPopAttrib(); +#endif } void Scene::render_quad_buffered_stereo() { +#if 0 glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glDrawBuffer(GL_BACK_LEFT); @@ -1814,6 +1815,7 @@ void Scene::render_quad_buffered_stereo() } this->render_scene_with_glow(); glDrawBuffer(GL_BACK); +#endif } }} // ns diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh index f35920a8377550b1ab4050560682188f94c63735..17182a20e7ab931e1913bfddb1e5fff9702ae82b 100644 --- a/modules/gfx/src/scene.hh +++ b/modules/gfx/src/scene.hh @@ -51,8 +51,8 @@ class OffscreenBuffer; typedef std::vector<SceneObserver*> SceneObserverList; struct Viewport { - int bottom; - int left; + int x; + int y; int width; int height; }; @@ -106,7 +106,7 @@ class DLLEXPORT_OST_GFX Scene { void SetShadow(bool f); /// \brief get shadow mapping status - bool GetShadow() const {return shadow_flag_;} + bool GetShadow() const; /// \brief shadow quality from 0 (low) to 3 (high), default=1 void SetShadowQuality(int q); @@ -409,14 +409,6 @@ private: bool axis_flag_; bool fog_flag_; Color fog_color_; - bool shadow_flag_; - int shadow_quality_; - GLuint shadow_tex_id_; - bool depth_dark_flag_; - bool amb_occl_flag_; - GLuint depth_tex_id_; - GLuint kernel_tex_id_; - GLuint scene_tex_id_; bool auto_autoslab_; bool offscreen_flag_; // a simple indicator whether in offscreen mode or not @@ -449,7 +441,8 @@ private: void stereo_projection(unsigned int view); void render_interlaced_stereo(); void render_quad_buffered_stereo(); - void render_scene_with_glow(); + void render_standard_scene(); + void render_glow(); bool IsNameAvailable(String name); }; diff --git a/modules/gfx/src/shader.cc b/modules/gfx/src/shader.cc index a3940c457238f78f00e543fda7b7620162643f04..3fed86bf6bad13dd1c54cc499d25435d5308ecd0 100644 --- a/modules/gfx/src/shader.cc +++ b/modules/gfx/src/shader.cc @@ -150,7 +150,9 @@ void Shader::Setup() {"outline_vs.glsl", GL_VERTEX_SHADER}, {"quadpp_vs.glsl", GL_VERTEX_SHADER}, {"convolute1_fs.glsl", GL_FRAGMENT_SHADER}, - {"amboccl_fs.glsl", GL_FRAGMENT_SHADER} + {"amboccl_fs.glsl", GL_FRAGMENT_SHADER}, + {"scenefx_vs.glsl", GL_VERTEX_SHADER}, + {"scenefx_fs.glsl", GL_FRAGMENT_SHADER} ////////////////////////////////////////////////////////////////// }; @@ -253,18 +255,25 @@ void Shader::Setup() } // convolute1 shader shader_program_list.clear(); - shader_program_list.push_back(shader_code_map_["quadpp.glsl"]); + shader_program_list.push_back(shader_code_map_["quadpp_vs.glsl"]); shader_program_list.push_back(shader_code_map_["convolute1_fs.glsl"]); if(link_shader(shader_program_list,"convolute1",shader_program_id)) { shader_program_map_["convolute1"]=shader_program_id; } - // amb occl shader + // amboccl shader shader_program_list.clear(); - shader_program_list.push_back(shader_code_map_["quadpp.glsl"]); + shader_program_list.push_back(shader_code_map_["quadpp_vs.glsl"]); shader_program_list.push_back(shader_code_map_["amboccl_fs.glsl"]); if(link_shader(shader_program_list,"amboccl",shader_program_id)) { shader_program_map_["amboccl"]=shader_program_id; } + // scenefx shader + shader_program_list.clear(); + shader_program_list.push_back(shader_code_map_["scenefx_vs.glsl"]); + shader_program_list.push_back(shader_code_map_["scenefx_fs.glsl"]); + if(link_shader(shader_program_list,"scenefx",shader_program_id)) { + shader_program_map_["scenefx"]=shader_program_id; + } valid_=true; } @@ -327,33 +336,6 @@ void Shader::PopProgram() } } -void Shader::SetShadowMapping(bool flag, GLuint texid) -{ - shadow_flag_=flag; - if(flag) { - shadow_map_id_=texid; - } - UpdateState(); -} - -void Shader::SetOcclusionMapping(bool flag, GLuint texid) -{ - occl_flag_=flag; - if(flag) { - occl_map_id_=texid; - } - UpdateState(); -} - -void Shader::SetDepthMapping(int mode, GLuint texid) -{ - depth_mode_=mode; - if(mode>0) { - depth_map_id_=texid; - } - UpdateState(); -} - void Shader::UpdateState() { if(current_program_!=0) { @@ -369,23 +351,6 @@ void Shader::UpdateState() glGetIntegerv(GL_FOG,&result); LOGN_TRACE("setting fog flag to " << result); glUniform1i(glGetUniformLocation(current_program_,"fog_flag"),result); - if(shadow_flag_) { - LOGN_TRACE("setting shadow flag to 1"); - glUniform1i(glGetUniformLocation(current_program_,"shadow_flag"),1); - glUniform1i(glGetUniformLocation(current_program_,"shadow_map"),shadow_map_id_); - glUniform1f(glGetUniformLocation(current_program_,"shadow_depth_bias"),0.008); - glUniform1f(glGetUniformLocation(current_program_,"shadow_epsilon"),0.002); - glUniform1f(glGetUniformLocation(current_program_,"shadow_multiplier"),0.4); - } else { - LOGN_TRACE("setting shadow flag to 0"); - glUniform1i(glGetUniformLocation(current_program_,"shadow_flag"),0); - } - LOGN_TRACE("setting depth mode to" << depth_mode_); - glUniform1i(glGetUniformLocation(current_program_,"depth_mode"),depth_mode_); - if(depth_mode_>0) { - glUniform1i(glGetUniformLocation(current_program_,"depth_map"),depth_map_id_); - } - glDisable(GL_COLOR_MATERIAL); } else { diff --git a/modules/gfx/src/shader.hh b/modules/gfx/src/shader.hh index b8938108f433527bd33eeb6fa5a2f63414f6fc77..8715e907cd9375966b3e465f674e7b31a46abab9 100644 --- a/modules/gfx/src/shader.hh +++ b/modules/gfx/src/shader.hh @@ -52,11 +52,6 @@ public: void PopProgram(); void UpdateState(); - - void SetShadowMapping(bool flag, GLuint texid); - void SetDepthMapping(int mode, GLuint texid); - void SetOcclusionMapping(bool flag, GLuint texid); - private: Shader(); @@ -64,13 +59,6 @@ private: GLuint current_program_; String current_name_; - bool shadow_flag_; - GLuint shadow_map_id_; - int depth_mode_; - GLuint depth_map_id_; - bool occl_flag_; - GLuint occl_map_id_; - std::stack<String> program_stack_; std::map<String,GLuint> shader_code_map_; diff --git a/modules/gfx/src/shader/amboccl_fs.glsl b/modules/gfx/src/shader/amboccl_fs.glsl index 44ad2220da64942e6d16e90396f36855bde2ec7e..76501a6cbda6754aea849c5d9071230f6941a6bd 100644 --- a/modules/gfx/src/shader/amboccl_fs.glsl +++ b/modules/gfx/src/shader/amboccl_fs.glsl @@ -1,6 +1,9 @@ -uniform sampler2D data; +uniform sampler2D depth; +uniform sampler2D norm; void main() { - gl_FragColor=texture2D(data,gl_TexCoord[0].xy); + float val = texture2D(depth,gl_TexCoord[0].xy).r; + gl_FragColor.rgb=1.0; + gl_FragColor.a=1.0; } diff --git a/modules/gfx/src/shader/basic_fs.glsl b/modules/gfx/src/shader/basic_fs.glsl index ceda497725ff8666bda220f6ab20e734bb66bae9..68059f4d1f084dcdd512e1c9f62fc409b15511d0 100644 --- a/modules/gfx/src/shader/basic_fs.glsl +++ b/modules/gfx/src/shader/basic_fs.glsl @@ -1,33 +1,10 @@ -uniform sampler2D shadow_map; -uniform bool shadow_flag; -uniform float shadow_depth_bias; -uniform float shadow_epsilon; -uniform float shadow_multiplier; uniform bool fog_flag; -float CalcShadowFactor(in vec4 coord, in vec2 o) -{ - // get original depth value of line projected towards light - float d = texture2D(shadow_map, coord.xy+o*shadow_epsilon).x+shadow_depth_bias; - return d<=coord.z ? shadow_multiplier : 1.0; -} - void main() { float fog = fog_flag ? clamp((gl_Fog.end-gl_FogFragCoord) * gl_Fog.scale, 0.0, 1.0) : 1.0; - if(shadow_flag) { - vec4 coord=gl_TexCoord[1]/gl_TexCoord[1].w; - float sum = 0.0; - sum += 0.18*CalcShadowFactor(coord, vec2(-0.7, -0.7)); - sum += 0.18*CalcShadowFactor(coord, vec2(0.7, -0.7)); - sum += 0.18*CalcShadowFactor(coord, vec2(0.7, 0.7)); - sum += 0.18*CalcShadowFactor(coord, vec2(-0.7, 0.7)); - sum += 0.28*CalcShadowFactor(coord, vec2(0, 0)); - - gl_FragColor = vec4(sum*mix(gl_Fog.color.rgb, gl_Color.rgb, fog),gl_Color.a); - } else { - gl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_Color.rgb, fog); - gl_FragColor.a = gl_Color.a; - } + gl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_Color.rgb, fog); + gl_FragColor.a = gl_Color.a; + gl_FragBuffer[1].rgb=gl_TexCoord[0].stp*0.5+0.5; } diff --git a/modules/gfx/src/shader/basic_vs.glsl b/modules/gfx/src/shader/basic_vs.glsl index 9f43289f6ab97923b819fa89c5fe71d6a6f5f43e..10cdf3a2439b017f7e922544e8f2c558e1038c16 100644 --- a/modules/gfx/src/shader/basic_vs.glsl +++ b/modules/gfx/src/shader/basic_vs.glsl @@ -56,6 +56,7 @@ void main() vec4 ec_Pos = gl_ModelViewMatrix* gl_Vertex; vec3 normal = normalize(gl_NormalMatrix * gl_Normal); + gl_TexCoord[0].stp = normal; if(lighting_flag) { CalcFrontAndBackColor(normal); diff --git a/modules/gfx/src/shader/fraglight_fs.glsl b/modules/gfx/src/shader/fraglight_fs.glsl index ac28cee890768a42313d1a3feb297b40a60b6937..a19d6b9a58f7017e8af5d859a6fda64a42ed3951 100644 --- a/modules/gfx/src/shader/fraglight_fs.glsl +++ b/modules/gfx/src/shader/fraglight_fs.glsl @@ -4,11 +4,6 @@ uniform bool fog_flag; uniform bool occlusion_flag; uniform vec2 ambient_weight; varying vec4 ambient_color; -uniform bool shadow_flag; -uniform sampler2D shadow_map; -uniform float shadow_depth_bias; -uniform float shadow_epsilon; -uniform float shadow_multiplier; uniform sampler2D depth_map; uniform int depth_mode; @@ -36,14 +31,6 @@ bool DirectionalLight(in vec3 normal, return true; } -// copy from basic_lfs_fs ! -float CalcShadowFactor(in vec4 coord, in vec2 o) -{ - // get original depth value of line projected towards light - float d = texture2D(shadow_map, coord.xy+o*shadow_epsilon).x+shadow_depth_bias; - return d<=coord.z ? shadow_multiplier : 1.0; -} - void main() { bool lflag=false; @@ -92,22 +79,7 @@ void main() } float fog = fog_flag ? clamp((gl_Fog.end-gl_FogFragCoord) * gl_Fog.scale, 0.0, 1.0) : 1.0; - if(shadow_flag) { - vec4 coord = gl_TexCoord[1]/gl_TexCoord[1].w; - float sum = 0.0; - if(lflag) { - sum += 0.18*CalcShadowFactor(coord, vec2(-0.7, -0.7)); - sum += 0.18*CalcShadowFactor(coord, vec2(0.7, -0.7)); - sum += 0.18*CalcShadowFactor(coord, vec2(0.7, 0.7)); - sum += 0.18*CalcShadowFactor(coord, vec2(-0.7, 0.7)); - sum += 0.28*CalcShadowFactor(coord, vec2(0, 0)); - } else { - sum = shadow_multiplier; - } - - gl_FragColor = vec4(sum*mix(gl_Fog.color.rgb, gl_FragColor.rgb, fog),gl_FragColor.a); - } else { - gl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_FragColor.rgb, fog); - gl_FragColor.a = gl_Color.a; - } + gl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_FragColor.rgb, fog); + gl_FragColor.a = gl_Color.a; + gl_FragBuffer[1].rgb=gl_TexCoord[0].stp*0.5+0.5; } diff --git a/modules/gfx/src/shader/quadpp_vs.glsl b/modules/gfx/src/shader/quadpp_vs.glsl index 5760f62116b23c27f68ef3f74d9e4a079429718c..043c65d69b2d1a4f96d705cc84d12ba9b847d592 100644 --- a/modules/gfx/src/shader/quadpp_vs.glsl +++ b/modules/gfx/src/shader/quadpp_vs.glsl @@ -1,6 +1,6 @@ void main() { gl_Position = ftransform(); - gl_TexCoord[0].st = 0.5*(gl_Position.xy+vec2(1.0,1.0)); + gl_TexCoord[0] = gl_MultiTexCoord0; } diff --git a/modules/gfx/src/shader/scenefx_fs.glsl b/modules/gfx/src/shader/scenefx_fs.glsl new file mode 100644 index 0000000000000000000000000000000000000000..83cc911d22c2a4c523ba629d0bef5a0a820053e3 --- /dev/null +++ b/modules/gfx/src/shader/scenefx_fs.glsl @@ -0,0 +1,42 @@ +uniform sampler2D scene; +uniform sampler2D depth; +uniform vec2 scalef; +uniform vec2 zmorph; +uniform bool shadow_flag; +uniform sampler2D shadow_map; +uniform float shadow_depth_bias; +uniform float shadow_epsilon; +uniform float shadow_multiplier; +uniform bool occl_flag; +uniform sampler2D occl_map; + +float CalcShadowFactor(in vec4 coord, in vec2 o) +{ + // get original depth value of line projected towards light + float d = texture2D(shadow_map, coord.xy+o*shadow_epsilon).x+shadow_depth_bias; + return d<=coord.z ? shadow_multiplier : 1.0; +} + +void main() +{ + float shadow_factor=1.0; + if(shadow_flag) { + // TODO: calculate appropriate coord from glTexCoord[1].xy and the depth map + vec4 coord; + 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)); + shadow_factor += 0.18*CalcShadowFactor(coord, vec2(0.7, 0.7)); + shadow_factor += 0.18*CalcShadowFactor(coord, vec2(-0.7, 0.7)); + shadow_factor += 0.28*CalcShadowFactor(coord, vec2(0, 0)); + } + + float occl_factor=1.0; + if(occl_flag) { + occl_factor=texture2D(occl_map,gl_TexCoord[0].xy).r; + } + + vec4 scene_color=texture2D(scene,gl_TexCoord[0].xy); + gl_FragColor.rgb = shadow_factor*occl_factor*scene_color.rgb; + gl_FragColor.a = scene_color.a; +} diff --git a/modules/gfx/src/shader/scenefx_vs.glsl b/modules/gfx/src/shader/scenefx_vs.glsl new file mode 100644 index 0000000000000000000000000000000000000000..59aa7bb4e40cb464102a85b54b902f36376398df --- /dev/null +++ b/modules/gfx/src/shader/scenefx_vs.glsl @@ -0,0 +1,8 @@ +void main() +{ + gl_Position = ftransform(); + // relative screen coordinates + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_Vertex; +} +