diff --git a/src/fgt/decorate_shadow/decorate_shader.h b/src/fgt/decorate_shadow/decorate_shader.h index dc15a4e01..f2a89babd 100644 --- a/src/fgt/decorate_shadow/decorate_shader.h +++ b/src/fgt/decorate_shadow/decorate_shader.h @@ -35,9 +35,8 @@ class DecorateShader public: DecorateShader(){ this->_initOk = false; - this->_texSize = 512; + this->_texSize = 1024; this->_shadowMap = 0; - // this->_color_tex = 0; } //virtual ~DecorateShader(); @@ -49,7 +48,6 @@ protected: bool _initOk; int _texSize; GLuint _shadowMap; - // GLuint _color_tex; virtual bool compileAndLink() = 0; virtual bool setup() = 0; diff --git a/src/fgt/decorate_shadow/decorate_shadow.cpp b/src/fgt/decorate_shadow/decorate_shadow.cpp index 483b2333d..3d97daa8c 100644 --- a/src/fgt/decorate_shadow/decorate_shadow.cpp +++ b/src/fgt/decorate_shadow/decorate_shadow.cpp @@ -29,10 +29,11 @@ const QString DecorateShadowPlugin::Info(QAction *action) { switch(ID(action)) { - case DP_SHOW_AO_DEPTH_TRICK : return tr("Enable ambient occlusion trick"); - case DP_SHOW_SIMPLE_SHADOW: return tr("Enable simple shadow"); - case DP_SHOW_SSAO: return tr("Enable SSAO"); - case DP_SHOW_VSM_SHADOW : return tr("Enable variance shadow mapping"); + case DP_SHOW_AO_DEPTH_TRICK : return tr("Enable ambient occlusion trick"); + case DP_SHOW_SIMPLE_SHADOW: return tr("Enable simple shadow"); + case DP_SHOW_SSAO: return tr("Enable SSAO"); + case DP_SHOW_VSM_SHADOW : return tr("Enable variance shadow mapping"); + case DP_SHOW_VSM_SHADOW_BLUR : return tr("Enable variance shadow mapping with blur"); } assert(0); return QString(); @@ -60,9 +61,10 @@ const QString DecorateShadowPlugin::ST(FilterIDType filter) const switch(filter) { case DP_SHOW_AO_DEPTH_TRICK : return QString("AO depth trick"); - case DP_SHOW_SIMPLE_SHADOW : return QString("simple shadow"); + case DP_SHOW_SIMPLE_SHADOW : return QString("Simple shadow"); case DP_SHOW_SSAO : return QString("SSAO"); - case DP_SHOW_VSM_SHADOW : return QString("VSM"); + case DP_SHOW_VSM_SHADOW : return QString("Variance shadow mapping"); + case DP_SHOW_VSM_SHADOW_BLUR : return QString("Variance shadow mapping blur"); default: assert(0); } return QString("error!"); @@ -74,6 +76,15 @@ bool DecorateShadowPlugin::StartDecorate(QAction* action, MeshModel& m, GLArea* result = this->_decorator = new ShadowMapping(); } + if(action->text() == ST(DP_SHOW_VSM_SHADOW)){ + result = this->_decorator = new VarianceShadowMapping(); + } + + if(action->text() == ST(DP_SHOW_VSM_SHADOW_BLUR)){ + result = this->_decorator = new VarianceShadowMappingBlur(); + } + + result = this->_decorator->init(); return result; } diff --git a/src/fgt/decorate_shadow/decorate_shadow.h b/src/fgt/decorate_shadow/decorate_shadow.h index 35cfca233..7d4495740 100644 --- a/src/fgt/decorate_shadow/decorate_shadow.h +++ b/src/fgt/decorate_shadow/decorate_shadow.h @@ -37,6 +37,8 @@ //#include #include "decorate_shader.h" #include "shadow_mapping.h" +#include "variance_shadow_mapping.h" +#include "variance_shadow_mapping_blur.h" class DecorateShadowPlugin : public QObject, public MeshDecorateInterface { @@ -47,6 +49,7 @@ class DecorateShadowPlugin : public QObject, public MeshDecorateInterface enum { DP_SHOW_SIMPLE_SHADOW, DP_SHOW_VSM_SHADOW, + DP_SHOW_VSM_SHADOW_BLUR, DP_SHOW_AO_DEPTH_TRICK, DP_SHOW_SSAO }; @@ -57,8 +60,10 @@ public: DecorateShadowPlugin() { - typeList << - DP_SHOW_SIMPLE_SHADOW ; + typeList << + DP_SHOW_SIMPLE_SHADOW << + DP_SHOW_VSM_SHADOW << + DP_SHOW_VSM_SHADOW_BLUR; FilterIDType tt; foreach(tt , types()){ @@ -68,7 +73,6 @@ public: foreach(ap,actionList){ ap->setCheckable(true); } - //this->_sm = new ShadowMapping(); } QList actions () const {return actionList;} @@ -77,7 +81,6 @@ public: virtual void initGlobalParameterSet(QAction *, FilterParameterSet * /*globalparam*/); private: DecorateShader* _decorator; - ShadowMapping* _sm; }; #endif diff --git a/src/fgt/decorate_shadow/decorate_shadow.pro b/src/fgt/decorate_shadow/decorate_shadow.pro index 93e02258b..e24c7f058 100644 --- a/src/fgt/decorate_shadow/decorate_shadow.pro +++ b/src/fgt/decorate_shadow/decorate_shadow.pro @@ -3,11 +3,15 @@ QT += opengl HEADERS = decorate_shadow.h \ shadow_mapping.h \ ../../../../vcglib/wrap/gui/trackball.h \ - decorate_shader.h + decorate_shader.h \ + variance_shadow_mapping.h \ + variance_shadow_mapping_blur.h SOURCES = decorate_shadow.cpp \ shadow_mapping.cpp \ ../../meshlab/filterparameter.cpp \ $$GLEWCODE \ ../../../../vcglib/wrap/gui/trackball.cpp \ - ../../../../vcglib/wrap/gui/trackmode.cpp + ../../../../vcglib/wrap/gui/trackmode.cpp \ + variance_shadow_mapping.cpp \ + variance_shadow_mapping_blur.cpp TARGET = decorate_shadow diff --git a/src/fgt/decorate_shadow/shader/sm/object.frag b/src/fgt/decorate_shadow/shader/sm/object.frag index f43d79dc9..bd01670c8 100644 --- a/src/fgt/decorate_shadow/shader/sm/object.frag +++ b/src/fgt/decorate_shadow/shader/sm/object.frag @@ -7,72 +7,8 @@ void main(){ //shadow2DProj fa automaticamente la divisione prospettica..al momento siamo in ortografica e nn serve shadowCoord.xyz = shadowCoord.xyz * 0.5 + 0.5; float sh = shadow2D(shadowMap, shadowCoord.xyz).x; - if (sh > 0.95) + if (sh > 0.4) discard; //else - gl_FragColor = vec4(vec3(0.0), 1.0); -} - - - -#if 0 - -uniform mat4 mvpl; - - -const float w = 0.5; -float pcf() -{ - float texel = 1.0/width; - vec4 depths; - vec4 ProjCoord = gl_TexCoord[0]; - depths[0] = texture2D(shadowMap, ProjCoord.st/ProjCoord.q + texel*vec2(-w, -w)).r; - depths[1] = texture2D(shadowMap, ProjCoord.st/ProjCoord.q + texel*vec2(+w, -w)).r; - depths[2] = texture2D(shadowMap, ProjCoord.st/ProjCoord.q + texel*vec2(-w, +w)).r; - depths[3] = texture2D(shadowMap, ProjCoord.st/ProjCoord.q + texel*vec2(+w, +w)).r; - - float r = ProjCoord.p / ProjCoord.q; - vec4 inShadow = vec4(lessThanEqual(vec4(r,r,r,r), depths+0.011)); - return dot(inShadow, vec4(0.25, 0.25, 0.25, 0.25)); -} - - -void main(void) -{ - - - // normalize vectors for lighting - vec3 nNormal = normalize(normalVec); - vec3 nLight = normalize(lightVec.xyz); - vec3 nView = normalize(viewVec); - - - // diffuse and specular contribution - float diffuse = clamp(dot(nLight, nNormal), 0.0, 1.0); - float specular = pow(clamp(dot(reflect(-nView, nNormal), nLight), 0.0, 1.0), 16.0); - //apply viewport transform to current frag distance from light - float depth = (lightDepth/2.0 + 0.5 ); - // retrieve stored depth from depthmap - // this is the same as: - //float sDepth = texture2D(shadowMap, gl_TexCoord[1].st/gl_TexCoord[1].q).r; - float sDepth = texture2DProj(shadowMap, gl_TexCoord[0]).q ; - - // compare distances to determine if fragment should be - // lit or shadowed - float shadow = (lightDepth < sDepth)? 1.0 : 0.0; - - vec4 Ka = gl_LightSource[0].ambient; - vec4 Kd = gl_LightSource[0].diffuse; - vec4 Ks = gl_LightSource[0].specular; - - // if fragment is shadowed, do not add specular and diffuse - // contribution - if(shadow == 0.0) - gl_FragColor = (Ka + (Kd * diffuse + Ks * specular)); - else - gl_FragColor = vec4(vec3(0.0), 1.0); - - - -} -#endif + gl_FragColor = vec4(sh); +} \ No newline at end of file diff --git a/src/fgt/decorate_shadow/shader/vsm/depthVSM.frag b/src/fgt/decorate_shadow/shader/vsm/depthVSM.frag new file mode 100644 index 000000000..9807cbfe7 --- /dev/null +++ b/src/fgt/decorate_shadow/shader/vsm/depthVSM.frag @@ -0,0 +1,16 @@ +varying vec4 point; + +void main(void) +{ + float depth = point.z;// / point.w; + depth = depth * 0.5 + 0.5; + + float moment1 = depth; + float moment2 = depth * depth; + + float dx = dFdx(depth); + float dy = dFdy(depth); + moment2 += 0.25 * (dx * dx + dy * dy); + + gl_FragColor = vec4(moment1, moment2 , 0.0, 1.0); +} \ No newline at end of file diff --git a/src/fgt/decorate_shadow/shader/vsm/depthVSM.vert b/src/fgt/decorate_shadow/shader/vsm/depthVSM.vert new file mode 100644 index 000000000..b7965dff7 --- /dev/null +++ b/src/fgt/decorate_shadow/shader/vsm/depthVSM.vert @@ -0,0 +1,6 @@ +varying vec4 point; + +void main(){ + gl_Position = ftransform(); + point = gl_Position; +} \ No newline at end of file diff --git a/src/fgt/decorate_shadow/shader/vsm/objectVSM.frag b/src/fgt/decorate_shadow/shader/vsm/objectVSM.frag new file mode 100644 index 000000000..033ab3823 --- /dev/null +++ b/src/fgt/decorate_shadow/shader/vsm/objectVSM.frag @@ -0,0 +1,33 @@ +uniform mat4 mvpl; +uniform sampler2D shadowMap; +uniform float texSize; +varying vec4 shadowCoord; + + +vec4 shadowCoordPostW; +float chebyshevUpperBound( float distance) { + // We retrive the two moments previously stored (depth and depth*depth) + vec2 moments = texture2D(shadowMap,shadowCoordPostW.xy).rb; + // Surface is fully lit. as the current fragment is before the light occluder + if (distance <= moments.x) + return 1.0 ; + + float variance = moments.y - (moments.x*moments.x); + //variance = max(variance,0.00002); + variance = max(variance,0.000195); + float d = distance - moments.x; + float p_max = variance / (variance + d*d); + return p_max; +} + +void main() { + shadowCoordPostW = shadowCoord / shadowCoord.w; + shadowCoordPostW = shadowCoordPostW * 0.5 + 0.5; + float shadow = chebyshevUpperBound(shadowCoordPostW.z); + + vec4 kd = gl_LightSource[0].diffuse; + if (shadow > 0.4) + discard; + + gl_FragColor = vec4(vec3(shadow), 1.0); +} \ No newline at end of file diff --git a/src/fgt/decorate_shadow/shader/vsm/objectVSM.vert b/src/fgt/decorate_shadow/shader/vsm/objectVSM.vert new file mode 100644 index 000000000..be4544c86 --- /dev/null +++ b/src/fgt/decorate_shadow/shader/vsm/objectVSM.vert @@ -0,0 +1,6 @@ +uniform mat4 mvpl; +varying vec4 shadowCoord; +void main() { +shadowCoord= mvpl * gl_Vertex; +gl_Position = ftransform(); +} \ No newline at end of file diff --git a/src/fgt/decorate_shadow/shadow_mapping.cpp b/src/fgt/decorate_shadow/shadow_mapping.cpp index 546592300..14b072d60 100644 --- a/src/fgt/decorate_shadow/shadow_mapping.cpp +++ b/src/fgt/decorate_shadow/shadow_mapping.cpp @@ -40,7 +40,7 @@ ShadowMapping::~ShadowMapping(){ glDeleteShader(this->_objectFrag); glDeleteProgram(this->_objectShaderProgram); - //glDeleteTextures(1, &(this->_color_tex)); + //glDeleteTextures(1, &(this->_color_tex)); glDeleteTextures(1, &(this->_shadowMap)); glDeleteFramebuffersEXT(1, &_fbo); @@ -124,7 +124,7 @@ void ShadowMapping::runShader(MeshModel& m, GLArea* gla){ RenderMode rm = gla->getCurrentRenderMode(); m.Render(rm.drawMode, rm.colorMode, rm.textureMode); glDisable(GL_POLYGON_OFFSET_FILL); - this->getShadowMap(); + //this->getShadowMap(); this->unbind(); // glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); @@ -167,20 +167,8 @@ bool ShadowMapping::setup() if (_initOk) return true; - - //COLOR - /*glGenTextures(1, &(this->_color_tex)); - glBindTexture(GL_TEXTURE_2D, this->_color_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, this->_texSize, this->_texSize, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); - */ - - - /*DEPTH*/ - glGenTextures(1, &this->_shadowMap); + /*DEPTH*/ + glGenTextures(1, &this->_shadowMap); glBindTexture(GL_TEXTURE_2D, this->_shadowMap); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); @@ -192,24 +180,24 @@ bool ShadowMapping::setup() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, this->_texSize, this->_texSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, this->_texSize, this->_texSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); - glGenFramebuffersEXT(1, &_fbo); + glGenFramebuffersEXT(1, &_fbo); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo); - //depth + //depth glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, this->_shadowMap, 0); - - //color - //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->_color_tex, 0/*mipmap level*/); - - //cosi specifichi che il colore non importa, che il fbo non ha niente sull'attachment colore + + //color + //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->_color_tex, 0/*mipmap level*/); + + //cosi specifichi che il colore non importa, che il fbo non ha niente sull'attachment colore GLenum drawBuffers[] = {GL_NONE}; glDrawBuffersARB(1, drawBuffers); - glReadBuffer(GL_NONE); - - int err = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + glReadBuffer(GL_NONE); + + int err = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); _initOk = (err == GL_FRAMEBUFFER_COMPLETE_EXT); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); return _initOk; @@ -223,7 +211,7 @@ void ShadowMapping::bind() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, this->_texSize, this->_texSize); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); } void ShadowMapping::unbind() @@ -253,6 +241,8 @@ bool ShadowMapping::compileAndLink(){ if(!this->printShaderInfoLog(this->_objectVert)) return false; + objVert->close(); + bArray = objFrag->readAll(); ShaderLen = (GLint) bArray.length(); ShaderSource = (GLubyte *)bArray.data(); @@ -263,6 +253,8 @@ bool ShadowMapping::compileAndLink(){ if(!this->printShaderInfoLog(this->_objectFrag)) return false; + objFrag->close(); + this->_objectShaderProgram = glCreateProgram(); glAttachShader(this->_objectShaderProgram, this->_objectVert); glAttachShader(this->_objectShaderProgram, this->_objectFrag); diff --git a/src/fgt/decorate_shadow/variance_shadow_mapping.cpp b/src/fgt/decorate_shadow/variance_shadow_mapping.cpp new file mode 100644 index 000000000..a102fe3f7 --- /dev/null +++ b/src/fgt/decorate_shadow/variance_shadow_mapping.cpp @@ -0,0 +1,291 @@ +#include "variance_shadow_mapping.h" + +VarianceShadowMapping::VarianceShadowMapping():DecorateShader() +{ + this->_depth = 0; + + this->_depthVert = 0; + this->_depthFrag = 0; + this->_depthShaderProgram = 0; + this->_objectVert = 0; + this->_objectFrag = 0; + this->_objectShaderProgram = 0; + this->_fbo = 0; +} + +VarianceShadowMapping::~VarianceShadowMapping(){ + glDetachShader(this->_depthShaderProgram, this->_depthVert); + glDetachShader(this->_depthShaderProgram, this->_depthFrag); + + glDeleteShader(this->_depthVert); + glDeleteShader(this->_depthFrag); + glDeleteProgram(this->_depthShaderProgram); + + glDetachShader(this->_objectShaderProgram, this->_objectVert); + glDetachShader(this->_objectShaderProgram, this->_objectFrag); + + glDeleteShader(this->_objectVert); + glDeleteShader(this->_objectFrag); + glDeleteProgram(this->_objectShaderProgram); + + glDeleteFramebuffersEXT(1, &(this->_depth)); + glDeleteTexturesEXT(1, &(this->_shadowMap)); + glDeleteFramebuffersEXT(1, &_fbo); +} + +bool VarianceShadowMapping::init() +{ + GLenum err = glewInit(); + if (!GLEW_OK == err){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle("GLEW init failure"); + msgBox.setText(QString("Init GLEW failed.")); + int ret = msgBox.exec(); + return false; + } + if(!this->setup()){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle("FBO Setup failure"); + msgBox.setText(QString("Failed in creating a Frame Buffer Object.")); + int ret = msgBox.exec(); + return false; + } + return compileAndLink(); +} + +void VarianceShadowMapping::runShader(MeshModel& m, GLArea* gla){ + vcg::Box3f bb = m.cm.bbox; + vcg::Point3f center; + center = bb.Center(); + + GLfloat g_mModelView[16]; + GLfloat g_mProjection[16]; + + int diag = bb.Diag(); + + GLfloat lP[4]; + glGetLightfv(GL_LIGHT0, GL_POSITION, lP); + vcg::Point3f light = -vcg::Point3f(lP[0],lP[1],lP[2]); + + vcg::Matrix44f tm = gla->trackball.Matrix(); + + glMatrixMode(GL_PROJECTION); + + glPushMatrix(); + + glLoadIdentity(); + glOrtho(-(diag/2), + diag/2, + -(diag/2), + diag/2, + -(diag/2), + diag/2); + + glGetFloatv(GL_PROJECTION_MATRIX, g_mProjection); + glMatrixMode(GL_MODELVIEW); + + glPushMatrix(); + vcg::Point3f u, v; + //mi seleziona automaticamente un upvector che mi eviti casi degeneri... + //nel caso vada bene 010 sceglie quello + vcg::GetUV(light, u, v, vcg::Point3f(0,-1,0)); + glLoadIdentity(); + gluLookAt(0, 0, 0, light[0], light[1], light[2], v[0], v[1], v[2]); + + //get the rotation matrix from the trackball + vcg::Matrix44f rotation; + vcg::Similarityf track = gla->trackball.track; + track.rot.ToMatrix(rotation); + glMultMatrixf(rotation.transpose().V()); + + //traslate the model in the center + glTranslatef(-center[0],-center[1],-center[2]); + glGetFloatv(GL_MODELVIEW_MATRIX, g_mModelView); + + + /***********************************************************/ + //GENERAZIONE SHADOW MAP + /***********************************************************/ + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1.0); + + + this->bind(); + glUseProgram(this->_depthShaderProgram); + RenderMode rm = gla->getCurrentRenderMode(); + m.Render(rm.drawMode, vcg::GLW::CMNone, vcg::GLW::TMNone); + glDisable(GL_POLYGON_OFFSET_FILL); + this->unbind(); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + /***********************************************************/ + //OBJECT PASS + /***********************************************************/ + GLint depthFuncOld; + glGetIntegerv(GL_DEPTH_FUNC, &depthFuncOld); + glDepthFunc(GL_LEQUAL); + vcg::Matrix44f mvpl = (vcg::Matrix44f(g_mProjection).transpose() * vcg::Matrix44f(g_mModelView).transpose()).transpose(); + glUseProgram(this->_objectShaderProgram); + + GLuint matrixLoc = glGetUniformLocation(this->_objectShaderProgram, "mvpl"); + glUniformMatrix4fv(matrixLoc, 1, 0, mvpl.V()); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, this->_shadowMap); + + GLuint loc = glGetUniformLocation(this->_objectShaderProgram, "shadowMap"); + glUniform1i(loc, 0); + m.Render(rm.drawMode, rm.colorMode, rm.textureMode); + glDepthFunc((GLenum)depthFuncOld); + glUseProgram(0); + + int error = glGetError(); +} + +bool VarianceShadowMapping::setup() +{ + if (!GLEW_EXT_framebuffer_object) { + qWarning("FBO not supported!"); + return false; + } + + if (_initOk) + return true; + + //genero il frame buffer object + glGenFramebuffersEXT(1, &_fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo); + + //genero la texture di colore che sara la mia variance shadow map. + glGenTextures(1, &this->_shadowMap); + glBindTexture(GL_TEXTURE_2D, this->_shadowMap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_texSize, this->_texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + //attacco al FBO la texture di colore + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->_shadowMap, 0); + + //genero il render buffer per il depth buffer + glGenRenderbuffersEXT(1, &(this->_depth)); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this->_depth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, this->_texSize, this->_texSize); + + //e il depth buffer + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, this->_depth); + + + int err = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + _initOk = (err == GL_FRAMEBUFFER_COMPLETE_EXT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + return _initOk; +} + +void VarianceShadowMapping::bind() +{ + assert(_initOk); + + glClearDepth(1.0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo); + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, this->_texSize, this->_texSize); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); +} + +void VarianceShadowMapping::unbind() +{ + if (!_initOk) + return; + + glPopAttrib(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + //glDeleteFramebuffersEXT(1, &_fbo); +} + +bool VarianceShadowMapping::compileAndLink(){ + QFile* depthVert = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsm/depthVSM.vert")); + QFile* depthFrag = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsm/depthVSM.frag")); + QFile* objVert = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsm/objectVSM.vert")); + QFile* objFrag = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsm/objectVSM.frag")); + + depthVert->open(QIODevice::ReadOnly | QIODevice::Text); + depthFrag->open(QIODevice::ReadOnly | QIODevice::Text); + + objVert->open(QIODevice::ReadOnly | QIODevice::Text); + objFrag->open(QIODevice::ReadOnly | QIODevice::Text); + + QByteArray bArray = depthVert->readAll(); + GLint ShaderLen = (GLint) bArray.length(); + GLubyte* ShaderSource = (GLubyte *)bArray.data(); + + this->_depthVert= glCreateShader(GL_VERTEX_SHADER); + glShaderSource(this->_depthVert, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_depthVert); + if(!this->printShaderInfoLog(this->_depthVert)) + return false; + + depthVert->close(); + + bArray = depthFrag->readAll(); + ShaderLen = (GLint) bArray.length(); + ShaderSource = (GLubyte *)bArray.data(); + + this->_depthFrag = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(this->_depthFrag, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_depthFrag); + if(!this->printShaderInfoLog(this->_depthFrag)) + return false; + + depthFrag->close(); + + this->_depthShaderProgram = glCreateProgram(); + glAttachShader(this->_depthShaderProgram, this->_depthVert); + glAttachShader(this->_depthShaderProgram, this->_depthFrag); + glLinkProgram(this->_depthShaderProgram); + if(!this->printProgramInfoLog(this->_depthShaderProgram)) + return false; + + + bArray = objVert->readAll(); + ShaderLen = (GLint) bArray.length(); + ShaderSource = (GLubyte *)bArray.data(); + + this->_objectVert= glCreateShader(GL_VERTEX_SHADER); + glShaderSource(this->_objectVert, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_objectVert); + if(!this->printShaderInfoLog(this->_objectVert)) + return false; + + objVert->close(); + + bArray = objFrag->readAll(); + ShaderLen = (GLint) bArray.length(); + ShaderSource = (GLubyte *)bArray.data(); + + this->_objectFrag= glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(this->_objectFrag, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_objectFrag); + if(!this->printShaderInfoLog(this->_objectFrag)) + return false; + + objFrag->close(); + + this->_objectShaderProgram = glCreateProgram(); + glAttachShader(this->_objectShaderProgram, this->_objectVert); + glAttachShader(this->_objectShaderProgram, this->_objectFrag); + glLinkProgram(this->_objectShaderProgram); + if(!this->printProgramInfoLog(this->_objectShaderProgram)) + return false; + + return true; +} + diff --git a/src/fgt/decorate_shadow/variance_shadow_mapping.h b/src/fgt/decorate_shadow/variance_shadow_mapping.h new file mode 100644 index 000000000..5a669f28e --- /dev/null +++ b/src/fgt/decorate_shadow/variance_shadow_mapping.h @@ -0,0 +1,43 @@ +#ifndef VARIANCE_SHADOW_MAPPING_H +#define VARIANCE_SHADOW_MAPPING_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BLUR_COEF 0.25 +#define SHADOW_COEF 0.5 + +class VarianceShadowMapping : public DecorateShader +{ + +public: + VarianceShadowMapping(); + ~VarianceShadowMapping(); + + bool init(); + void runShader(MeshModel&, GLArea*); + +private: + bool compileAndLink(); + bool setup(); + void bind(); + void unbind(); + + GLuint _depth; + + GLuint _fbo; + GLuint _objectShaderProgram; + GLuint _objectVert, _objectFrag; + GLuint _depthShaderProgram; + GLuint _depthVert, _depthFrag; +}; + + +#endif // VARIANCE_SHADOW_MAPPING_H diff --git a/src/fgt/decorate_shadow/variance_shadow_mapping_blur.cpp b/src/fgt/decorate_shadow/variance_shadow_mapping_blur.cpp new file mode 100644 index 000000000..6f1002576 --- /dev/null +++ b/src/fgt/decorate_shadow/variance_shadow_mapping_blur.cpp @@ -0,0 +1,470 @@ +#include "variance_shadow_mapping_blur.h" + +VarianceShadowMappingBlur::VarianceShadowMappingBlur():DecorateShader() +{ + this->_depth = 0; + this->_blur = 0; + + this->_depthVert = 0; + this->_depthFrag = 0; + this->_depthShaderProgram = 0; + this->_objectVert = 0; + this->_objectFrag = 0; + this->_objectShaderProgram = 0; + this->_blurVert = 0; + this->_blurFrag = 0; + this->_blurShaderProgram = 0; + this->_fbo = 0; +} + +VarianceShadowMappingBlur::~VarianceShadowMappingBlur(){ + glDetachShader(this->_depthShaderProgram, this->_depthVert); + glDetachShader(this->_depthShaderProgram, this->_depthFrag); + + glDeleteShader(this->_depthVert); + glDeleteShader(this->_depthFrag); + glDeleteProgram(this->_depthShaderProgram); + + glDetachShader(this->_objectShaderProgram, this->_objectVert); + glDetachShader(this->_objectShaderProgram, this->_objectFrag); + + glDeleteShader(this->_objectVert); + glDeleteShader(this->_objectFrag); + glDeleteProgram(this->_objectShaderProgram); + + glDetachShader(this->_blurShaderProgram, this->_blurVert); + glDetachShader(this->_blurShaderProgram, this->_blurFrag); + + glDeleteShader(this->_blurVert); + glDeleteShader(this->_blurFrag); + glDeleteProgram(this->_blurShaderProgram); + + glDeleteFramebuffersEXT(1, &(this->_depth)); + glDeleteTexturesEXT(1, &(this->_shadowMap)); + glDeleteTexturesEXT(1, &(this->_blur)); + glDeleteFramebuffersEXT(1, &_fbo); +} + +bool VarianceShadowMappingBlur::init() +{ + GLenum err = glewInit(); + if (!GLEW_OK == err){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle("GLEW init failure"); + msgBox.setText(QString("Init GLEW failed.")); + int ret = msgBox.exec(); + return false; + } + if(!this->setup()){ + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle("FBO Setup failure"); + msgBox.setText(QString("Failed in creating a Frame Buffer Object.")); + int ret = msgBox.exec(); + return false; + } + return compileAndLink(); +} + +void VarianceShadowMappingBlur::runShader(MeshModel& m, GLArea* gla){ + vcg::Box3f bb = m.cm.bbox; + vcg::Point3f center; + center = bb.Center(); + + GLfloat g_mModelView[16]; + GLfloat g_mProjection[16]; + + int diag = bb.Diag(); + + GLfloat lP[4]; + glGetLightfv(GL_LIGHT0, GL_POSITION, lP); + vcg::Point3f light = -vcg::Point3f(lP[0],lP[1],lP[2]); + + vcg::Matrix44f tm = gla->trackball.Matrix(); + + glMatrixMode(GL_PROJECTION); + + glPushMatrix(); + + glLoadIdentity(); + glOrtho(-(diag/2), + diag/2, + -(diag/2), + diag/2, + -(diag/2), + diag/2); + + glGetFloatv(GL_PROJECTION_MATRIX, g_mProjection); + glMatrixMode(GL_MODELVIEW); + + glPushMatrix(); + vcg::Point3f u, v; + //mi seleziona automaticamente un upvector che mi eviti casi degeneri...nel caso vada bene 010 sceglie quello + vcg::GetUV(light, u, v, vcg::Point3f(0,-1,0)); + glLoadIdentity(); + gluLookAt(0, 0, 0, light[0], light[1], light[2], v[0], v[1], v[2]); + + //get the rotation matrix from the trackball + vcg::Matrix44f rotation; + vcg::Similarityf track = gla->trackball.track; + track.rot.ToMatrix(rotation); + glMultMatrixf(rotation.transpose().V()); + + //traslate the model in the center + glTranslatef(-center[0],-center[1],-center[2]); + glGetFloatv(GL_MODELVIEW_MATRIX, g_mModelView); + + + /***********************************************************/ + //GENERAZIONE SHADOW MAP + /***********************************************************/ + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1.0); + + + this->bind(); + glUseProgram(this->_depthShaderProgram); + RenderMode rm = gla->getCurrentRenderMode(); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m.Render(rm.drawMode, vcg::GLW::CMNone, vcg::GLW::TMNone); + glDisable(GL_POLYGON_OFFSET_FILL); + //this->getShadowMap(); + //glUseProgram(0); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + /***********************************************************/ + //OBJECT PASS + /***********************************************************/ + GLint depthFuncOld; + glGetIntegerv(GL_DEPTH_FUNC, &depthFuncOld); + glDepthFunc(GL_LEQUAL); + vcg::Matrix44f mvpl = (vcg::Matrix44f(g_mProjection).transpose() * vcg::Matrix44f(g_mModelView).transpose()).transpose(); + glUseProgram(this->_objectShaderProgram); + + GLuint matrixLoc = glGetUniformLocation(this->_objectShaderProgram, "mvpl"); + glUniformMatrix4fv(matrixLoc, 1, 0, mvpl.V()); + + glEnable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, this->_shadowMap); + + + GLuint loc = glGetUniformLocation(this->_objectShaderProgram, "shadowMap"); + glUniform1i(loc, 0); + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m.Render(rm.drawMode, rm.colorMode, rm.textureMode); + + //this->getBlur(); + this->unbind(); + glDepthFunc((GLenum)depthFuncOld); + glUseProgram(0); + + /***********************************************************/ + //BLURRING + /***********************************************************/ + glUseProgram(this->_blurShaderProgram); + + //GLfloat scale = 1/(diag * BLUR_COEF * SHADOW_COEF); + GLfloat scale = (1/(this->_texSize)) * BLUR_COEF * SHADOW_COEF; + + GLuint scaleLoc = glGetUniformLocation(this->_blurShaderProgram, "scale"); + //glUniform2f(scaleLoc, 0.0, 0.0); + glUniform2f(scaleLoc, scale, scale); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, this->_blur); + loc = glGetUniformLocation(this->_blurShaderProgram, "scene"); + glUniform1i(loc, 0); + + //Preparing to draw quad + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + /*glOrtho(-(diag/2), + diag/2, + -(diag/2), + diag/2, + -(diag/2), + diag/2);*/ + glOrtho(-(this->_texSize/2), + this->_texSize/2, + -(this->_texSize/2), + this->_texSize/2, + -(this->_texSize/2), + this->_texSize/2); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + //glTranslated(0,0,-(diag/2)); + glTranslated(0,0,-5); + + + glBegin(GL_QUADS); + glTexCoord2d(0,0);glVertex3f(-this->_texSize/2,-this->_texSize/2,0); + glTexCoord2d(1,0);glVertex3f(this->_texSize/2,-this->_texSize/2,0); + glTexCoord2d(1,1);glVertex3f(this->_texSize/2,this->_texSize/2,0); + glTexCoord2d(0,1);glVertex3f(-this->_texSize/2,this->_texSize/2,0); + glEnd(); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + //m.Render(rm.drawMode, rm.colorMode, rm.textureMode); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glUseProgram(0); + + int error = glGetError(); +} + +bool VarianceShadowMappingBlur::setup() +{ + if (!GLEW_EXT_framebuffer_object) { + qWarning("FBO not supported!"); + return false; + } + + if (_initOk) + return true; + + //genero il frame buffer object + glGenFramebuffersEXT(1, &_fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo); + + //genero la texture di colore che sara la mia variance shadow map. + glGenTextures(1, &this->_shadowMap); + glBindTexture(GL_TEXTURE_2D, this->_shadowMap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F_ARB, this->_texSize, this->_texSize, 0, GL_RGB, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_texSize, this->_texSize, 0, GL_RGBA, GL_FLOAT, NULL); + //attacco al FBO la texture di colore + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->_shadowMap, 0); + + //genero la texture di blur. + glGenTextures(1, &this->_blur); + glBindTexture(GL_TEXTURE_2D, this->_blur); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F_ARB, this->_texSize, this->_texSize, 0, GL_RGB, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_texSize, this->_texSize, 0, GL_RGBA, GL_FLOAT, NULL); + //e la texture per il blur + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, this->_blur, 0); + + //genero il render buffer per il depth buffer + glGenRenderbuffersEXT(1, &(this->_depth)); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this->_depth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, this->_texSize, this->_texSize); + + //e il depth buffer + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, this->_depth); + GLenum drawBuffers[] = {this->_shadowMap, this->_blur}; + glDrawBuffersARB(2, drawBuffers); + + int err = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + _initOk = (err == GL_FRAMEBUFFER_COMPLETE_EXT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + return _initOk; +} + +void VarianceShadowMappingBlur::bind() +{ + assert(_initOk); + + glClearDepth(1.0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo); + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, this->_texSize, this->_texSize); + //glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); +} + +void VarianceShadowMappingBlur::unbind() +{ + if (!_initOk) + return; + + glPopAttrib(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + //glDeleteFramebuffersEXT(1, &_fbo); +} + +bool VarianceShadowMappingBlur::compileAndLink(){ + QFile* depthVert = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsmb/depthVSM.vert")); + QFile* depthFrag = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsmb/depthVSM.frag")); + QFile* objVert = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsmb/objectVSM.vert")); + QFile* objFrag = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsmb/objectVSM.frag")); + QFile* blurVert = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsmb/blurVSM.vert")); + QFile* blurFrag = new QFile(MainWindowInterface::getBaseDirPath() + QString("/../fgt/decorate_shadow/shader/vsmb/blurVSM.frag")); + + depthVert->open(QIODevice::ReadOnly | QIODevice::Text); + depthFrag->open(QIODevice::ReadOnly | QIODevice::Text); + + objVert->open(QIODevice::ReadOnly | QIODevice::Text); + objFrag->open(QIODevice::ReadOnly | QIODevice::Text); + + blurVert->open(QIODevice::ReadOnly | QIODevice::Text); + blurFrag->open(QIODevice::ReadOnly | QIODevice::Text); + + QByteArray bArray = depthVert->readAll(); + GLint ShaderLen = (GLint) bArray.length(); + GLubyte* ShaderSource = (GLubyte *)bArray.data(); + + depthVert->close(); + + this->_depthVert= glCreateShader(GL_VERTEX_SHADER); + glShaderSource(this->_depthVert, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_depthVert); + if(!this->printShaderInfoLog(this->_depthVert)) + return false; + + bArray = depthFrag->readAll(); + ShaderLen = (GLint) bArray.length(); + ShaderSource = (GLubyte *)bArray.data(); + + depthFrag->close(); + + this->_depthFrag = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(this->_depthFrag, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_depthFrag); + if(!this->printShaderInfoLog(this->_depthFrag)) + return false; + + this->_depthShaderProgram = glCreateProgram(); + glAttachShader(this->_depthShaderProgram, this->_depthVert); + glAttachShader(this->_depthShaderProgram, this->_depthFrag); + glLinkProgram(this->_depthShaderProgram); + if(!this->printProgramInfoLog(this->_depthShaderProgram)) + return false; + + + bArray = objVert->readAll(); + ShaderLen = (GLint) bArray.length(); + ShaderSource = (GLubyte *)bArray.data(); + + objVert->close(); + + this->_objectVert= glCreateShader(GL_VERTEX_SHADER); + glShaderSource(this->_objectVert, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_objectVert); + if(!this->printShaderInfoLog(this->_objectVert)) + return false; + + bArray = objFrag->readAll(); + ShaderLen = (GLint) bArray.length(); + ShaderSource = (GLubyte *)bArray.data(); + + objFrag->close(); + + this->_objectFrag= glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(this->_objectFrag, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_objectFrag); + if(!this->printShaderInfoLog(this->_objectFrag)) + return false; + + this->_objectShaderProgram = glCreateProgram(); + glAttachShader(this->_objectShaderProgram, this->_objectVert); + glAttachShader(this->_objectShaderProgram, this->_objectFrag); + glLinkProgram(this->_objectShaderProgram); + if(!this->printProgramInfoLog(this->_objectShaderProgram)) + return false; + + bArray = blurVert->readAll(); + ShaderLen = (GLint) bArray.length(); + ShaderSource = (GLubyte *)bArray.data(); + + blurVert->close(); + + this->_blurVert = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(this->_blurVert, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_blurVert); + if(!this->printShaderInfoLog(this->_blurVert)) + return false; + + bArray = blurFrag->readAll(); + ShaderLen = (GLint) bArray.length(); + ShaderSource = (GLubyte *)bArray.data(); + + blurFrag->close(); + + this->_blurFrag= glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(this->_blurFrag, 1, (const GLchar **)&ShaderSource, &ShaderLen); + glCompileShader(this->_blurFrag); + if(!this->printShaderInfoLog(this->_blurFrag)) + return false; + + this->_blurShaderProgram = glCreateProgram(); + glAttachShader(this->_blurShaderProgram, this->_blurVert); + glAttachShader(this->_blurShaderProgram, this->_blurFrag); + glLinkProgram(this->_blurShaderProgram); + if(!this->printProgramInfoLog(this->_blurShaderProgram)) + return false; + + return true; +} + +void VarianceShadowMappingBlur::getBlur() +{ + if (!this->_initOk) + return; + + QImage img(this->_texSize, this->_texSize, QImage::Format_RGB32); + + unsigned char *tempBuf = new unsigned char[this->_texSize * this->_texSize * 3]; + unsigned char *tempBufPtr = tempBuf; + glBindTexture(GL_TEXTURE_2D, this->_blur); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, tempBufPtr); + for (int i = 0; i < this->_texSize; ++i) { + QRgb *scanLine = (QRgb*)img.scanLine(i); + for (int j = 0; j < this->_texSize; ++j) { + scanLine[j] = qRgb(tempBufPtr[0], tempBufPtr[1], tempBufPtr[2]); + tempBufPtr += 3; + } + } + + delete[] tempBuf; + + img.mirrored().save("./_vsm_blurTXT.png", "PNG"); +} + +void VarianceShadowMappingBlur::getShadowMap(){ + if (!this->_initOk) + return; + + QImage img(this->_texSize, this->_texSize, QImage::Format_RGB32); + + unsigned char *tempBuf = new unsigned char[this->_texSize * this->_texSize * 3]; + unsigned char *tempBufPtr = tempBuf; + glBindTexture(GL_TEXTURE_2D, this->_shadowMap); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, tempBufPtr); + for (int i = 0; i < this->_texSize; ++i) { + QRgb *scanLine = (QRgb*)img.scanLine(i); + for (int j = 0; j < this->_texSize; ++j) { + scanLine[j] = qRgb(tempBufPtr[0], tempBufPtr[1], tempBufPtr[2]); + tempBufPtr += 3; + } + } + + delete[] tempBuf; + img.mirrored().save("./_shadowMapTXT.png", "PNG"); + } + diff --git a/src/fgt/decorate_shadow/variance_shadow_mapping_blur.h b/src/fgt/decorate_shadow/variance_shadow_mapping_blur.h new file mode 100644 index 000000000..52369d7ed --- /dev/null +++ b/src/fgt/decorate_shadow/variance_shadow_mapping_blur.h @@ -0,0 +1,47 @@ +#ifndef VARIANCE_SHADOW_MAPPING_BLUR_H +#define VARIANCE_SHADOW_MAPPING_BLUR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BLUR_COEF 0.25 +#define SHADOW_COEF 0.5 + +class VarianceShadowMappingBlur : public DecorateShader +{ + +public: + VarianceShadowMappingBlur(); + ~VarianceShadowMappingBlur(); + + bool init(); + void runShader(MeshModel&, GLArea*); + +private: + bool compileAndLink(); + bool setup(); + void bind(); + void unbind(); + void getBlur(); + void getShadowMap(); + + GLuint _depth; + GLuint _blur; + + GLuint _fbo; + GLuint _objectShaderProgram; + GLuint _objectVert, _objectFrag; + GLuint _depthShaderProgram; + GLuint _depthVert, _depthFrag; + GLuint _blurShaderProgram; + GLuint _blurVert, _blurFrag; +}; + +#endif // VARIANCE_SHADOW_MAPPING_BLUR_H