diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc index f5658f464db25b7661aa0d3e1695d35186c62895..cd7a902a292b4cc2dafe1172ed5d479081ad99f5 100644 --- a/modules/gfx/pymod/export_scene.cc +++ b/modules/gfx/pymod/export_scene.cc @@ -119,6 +119,7 @@ void export_Scene() .def("SetShadowQuality",&Scene::SetShadowQuality) .def("SetDepthDarkening",&Scene::SetDepthDarkening) .def("SetAmbientOcclusion",&Scene::SetAmbientOcclusion) + .def("SetAmbientOcclusionFactor",&Scene::SetAmbientOcclusionFactor) .def("AttachObserver",&Scene::AttachObserver) .def("StartOffscreenMode",&Scene::StartOffscreenMode) .def("StopOffscreenMode",&Scene::StopOffscreenMode) diff --git a/modules/gfx/src/impl/scene_fx.cc b/modules/gfx/src/impl/scene_fx.cc index 08b0ed4c4a370c18bcd70870fd0c2b47b79cd9d8..4c70d8417291f903256d69b6f85bfd3355aae205 100644 --- a/modules/gfx/src/impl/scene_fx.cc +++ b/modules/gfx/src/impl/scene_fx.cc @@ -1,3 +1,5 @@ +#include <boost/random.hpp> + #include "scene_fx.hh" #include <ost/log.hh> @@ -8,6 +10,11 @@ namespace ost { namespace gfx { namespace impl { +namespace { + boost::mt19937 RandomGenerator(time(NULL)); + boost::uniform_01<boost::mt19937> UniformRandom(RandomGenerator); +} + SceneFX& SceneFX::Instance() { static SceneFX inst; @@ -19,12 +26,15 @@ SceneFX::SceneFX(): shadow_quality(1), depth_dark_flag(false), amb_occl_flag(false), + amb_occl_factor(1.0), scene_tex_id_(), depth_tex_id_(), shadow_tex_id_(), occl_tex_id_(), dark_tex_id_(), norm_tex_id_(), + kernel_tex_id_(), + kernel_size_(0), scene_tex2_id_(), norm_tex2_id_(), scene_fb_(), @@ -45,14 +55,13 @@ void SceneFX::Setup() glGenTextures(1,&occl_tex_id_); glGenTextures(1,&dark_tex_id_); glGenTextures(1,&norm_tex_id_); + glGenTextures(1,&kernel_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); @@ -72,14 +81,14 @@ void SceneFX::Setup() 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_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); 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_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); @@ -89,6 +98,29 @@ void SceneFX::Setup() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_1D, kernel_tex_id_); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); + + std::vector<GLfloat> tmp; + for(int u=-20;u<=20;++u) { + for(int v=-20;v<=20;++v) { + if(UniformRandom()<0.1) { + // norm to 1 + float x = static_cast<float>(u+20)*0.025; + float y = static_cast<float>(v+20)*0.025; + tmp.push_back(x); + tmp.push_back(y); + tmp.push_back(0.0); + tmp.push_back(0.0); + } + } + } + + kernel_size_=tmp.size()/4; + glTexImage1D(GL_TEXTURE_1D,0,4,kernel_size_,0,GL_RGBA, GL_FLOAT, &tmp[0]); } void SceneFX::Resize(unsigned int w, unsigned int h) @@ -149,9 +181,9 @@ void SceneFX::Postprocess() Shader::Instance().Activate("dumpnorm"); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); Scene::Instance().GetRootNode()->RenderGL(STANDARD_RENDER_PASS); - Shader::Instance().PopProgram(); glBindTexture(GL_TEXTURE_2D, norm_tex_id_); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, vp.x, vp.y, vp.width, vp.height, 0); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vp.x, vp.y, vp.width, vp.height, 0); + Shader::Instance().PopProgram(); } } @@ -160,8 +192,6 @@ void SceneFX::Postprocess() } if(amb_occl_flag) { prep_amb_occlusion(); - draw_debug_tex(vp.width,vp.height,occl_tex_id_); - return; } if(depth_dark_flag) { //prep_depth_darkening(); @@ -170,12 +200,13 @@ void SceneFX::Postprocess() Shader::Instance().PushProgram(); glEnable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_1D); Shader::Instance().Activate("scenefx"); + GLuint cpr=Shader::Instance().GetCurrentProgram(); 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"), @@ -196,16 +227,15 @@ void SceneFX::Postprocess() } 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); + glUniform1f(glGetUniformLocation(cpr,"occl_mult"),amb_occl_factor); } else { glUniform1i(glGetUniformLocation(cpr,"occl_flag"),0); } -#endif draw_screen_quad(vp.width,vp.height); glDisable(GL_TEXTURE_2D); @@ -289,6 +319,9 @@ void SceneFX::prep_amb_occlusion() { Viewport vp=Scene::Instance().GetViewport(); + uint width=vp.width/2; + uint height=vp.height/2; + Shader::Instance().PushProgram(); Shader::Instance().Activate("amboccl"); GLuint cpr=Shader::Instance().GetCurrentProgram(); @@ -297,15 +330,23 @@ void SceneFX::prep_amb_occlusion() 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); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_1D,kernel_tex_id_); + glUniform1i(glGetUniformLocation(cpr,"depth_map"),0); + glUniform1i(glGetUniformLocation(cpr,"norm_map"),1); + glUniform1i(glGetUniformLocation(cpr,"kernel"),2); + glUniform1f(glGetUniformLocation(cpr,"step"),1.0/static_cast<float>(kernel_size_)); + glUniform2f(glGetUniformLocation(cpr,"i_vp"),1.0/static_cast<float>(width),1.0/static_cast<float>(height)); + double pm[16]; + glGetDoublev(GL_PROJECTION_MATRIX,pm); + glUniform4f(glGetUniformLocation(cpr,"abcd"),pm[0],pm[5],pm[10],pm[14]); // set up viewport filling quad to run the fragment shader - draw_screen_quad(vp.width,vp.height); + draw_screen_quad(width,height); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, occl_tex_id_); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0,0, vp.width, vp.height, 0); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0,0, width, height, 0); Shader::Instance().PopProgram(); } diff --git a/modules/gfx/src/impl/scene_fx.hh b/modules/gfx/src/impl/scene_fx.hh index 6db023e03987e0fbe34ac41e51ef9cf3f2304619..884ae425a9bdefed8053b012c7bcb3610e145012 100644 --- a/modules/gfx/src/impl/scene_fx.hh +++ b/modules/gfx/src/impl/scene_fx.hh @@ -50,6 +50,7 @@ public: int shadow_quality; bool depth_dark_flag; bool amb_occl_flag; + float amb_occl_factor; private: SceneFX(); @@ -68,6 +69,8 @@ private: GLuint occl_tex_id_; GLuint dark_tex_id_; GLuint norm_tex_id_; + GLuint kernel_tex_id_; + uint kernel_size_; GLuint scene_tex2_id_; GLuint norm_tex2_id_; diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc index 6c8bbded8a36d710529892a2d4b33682600aefef..028b78fbd2c7cbdb76c036c1d4c1ddd268360ac2 100644 --- a/modules/gfx/src/scene.cc +++ b/modules/gfx/src/scene.cc @@ -198,6 +198,15 @@ void Scene::SetAmbientOcclusion(bool f) // the redraw routine will deal with the Shader RequestRedraw(); #endif +} + +void Scene::SetAmbientOcclusionFactor(float f) +{ +#if OST_SHADER_SUPPORT_ENABLED + impl::SceneFX::Instance().amb_occl_factor=f; + // the redraw routine will deal with the Shader + RequestRedraw(); +#endif } void Scene::SetShadingMode(const std::string& smode) diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh index 17182a20e7ab931e1913bfddb1e5fff9702ae82b..bedf2774fef15c02ae88c7cd39e269ea838a22e7 100644 --- a/modules/gfx/src/scene.hh +++ b/modules/gfx/src/scene.hh @@ -114,6 +114,7 @@ class DLLEXPORT_OST_GFX Scene { void SetDepthDarkening(bool f); void SetAmbientOcclusion(bool f); + void SetAmbientOcclusionFactor(float f); /// \brief select shading mode /// one of fallback, basic, default, hf, toon1, toon2 diff --git a/modules/gfx/src/shader/amboccl_fs.glsl b/modules/gfx/src/shader/amboccl_fs.glsl index 1a6a365def90e6e9b7c845c40affbde8ad95f1d1..b1a8be162a5d25181a828f3a16623d1e1474bb1f 100644 --- a/modules/gfx/src/shader/amboccl_fs.glsl +++ b/modules/gfx/src/shader/amboccl_fs.glsl @@ -1,9 +1,51 @@ -uniform sampler2D depth; -uniform sampler2D norm; +uniform sampler2D depth_map; +uniform sampler2D norm_map; +uniform sampler1D kernel; +uniform float step; +uniform vec2 i_vp; +uniform vec4 abcd; + +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 ao(in vec2 tab, in vec3 pos_p, in vec3 norm_p, in vec3 t_pos_p) +{ + float depth_q = texture2D(depth_map,gl_TexCoord[0].xy+tab.xy*i_vp).r; + if(depth_q>=1.0) { + return 0.0; + } + vec3 pos_q = vec3(gl_FragCoord.xy+tab.xy,depth_q); + vec3 t_pos_q = unproject(pos_q); + + vec3 diff=t_pos_q-t_pos_p; + float fac=1.0+dot(diff,diff)/25.0; + return max(0.0,dot(normalize(norm_p),normalize(diff)))/fac; +} void main() { - float val = texture2D(depth,gl_TexCoord[0].xy).r; - gl_FragColor.rgb=vec3(val,val,val); + float depth_p = texture2D(depth_map,gl_TexCoord[0].xy).r; + if(depth_p>=1.0) { + gl_FragColor = vec4(0,0,0,1); + return; + } + vec3 norm_p = (texture2D(norm_map,gl_TexCoord[0].xy).xyz-0.5)*2.0; + vec3 pos_p = vec3(gl_FragCoord.xy,depth_p); + vec3 t_pos_p = unproject(pos_p); + + float i; + float sum=0.0; + for(i=0.0;i<1.0;i+=step) { + vec2 nn=texture1D(kernel,i).xy; + nn=(nn-0.5)*40.0; + sum+=ao(nn,pos_p,norm_p,t_pos_p); + } + sum*=step; + + gl_FragColor.rgb=vec3(sum,sum,sum); gl_FragColor.a=1.0; } diff --git a/modules/gfx/src/shader/scenefx_fs.glsl b/modules/gfx/src/shader/scenefx_fs.glsl index 83cc911d22c2a4c523ba629d0bef5a0a820053e3..ce63193f1cc7e48dbce6a74363bffaf97eb8335b 100644 --- a/modules/gfx/src/shader/scenefx_fs.glsl +++ b/modules/gfx/src/shader/scenefx_fs.glsl @@ -9,6 +9,7 @@ uniform float shadow_epsilon; uniform float shadow_multiplier; uniform bool occl_flag; uniform sampler2D occl_map; +uniform float occl_mult; float CalcShadowFactor(in vec4 coord, in vec2 o) { @@ -33,7 +34,7 @@ void main() float occl_factor=1.0; if(occl_flag) { - occl_factor=texture2D(occl_map,gl_TexCoord[0].xy).r; + occl_factor=max(0.0,1.0-occl_mult*texture2D(occl_map,gl_TexCoord[0].xy).r); } vec4 scene_color=texture2D(scene,gl_TexCoord[0].xy);