First partially working version of shadow mapping.

We still have to add world matrix in the first rendering pass.
this version should work only with centered models.
This commit is contained in:
Paolo Cignoni cignoni 2009-07-10 14:22:54 +00:00
parent fb23a9352d
commit 7fa41bd3ef
5 changed files with 141 additions and 138 deletions

View File

@ -1,15 +1,11 @@
include (../../shared.pri)
QT += opengl
HEADERS = decorate_shadow.h \
shadow_mapping.h
SOURCES = decorate_shadow.cpp \
shadow_mapping.cpp \
../../meshlab/filterparameter.cpp \
$$GLEWCODE
TARGET = decorate_shadow
QT += opengl
HEADERS = decorate_shadow.h \
shadow_mapping.h
SOURCES = decorate_shadow.cpp \
shadow_mapping.cpp \
../../meshlab/filterparameter.cpp \
$$GLEWCODE \
../../../../vcglib/wrap/gui/trackball.cpp \
../../../../vcglib/wrap/gui/trackmode.cpp
TARGET = decorate_shadow

View File

@ -1,10 +1,23 @@
uniform sampler2D shadowMap;
uniform float width;
varying vec3 normalVec;
varying float lightDepth; //current frag distance from light
varying vec3 viewVec;
varying vec3 lightVec;
uniform mat4 mvpl;
uniform sampler2DShadow shadowMap;
varying vec4 pPos;
void main(){
vec4 shadowCoord = mvpl * pPos;
//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)
discard;
//else
gl_FragColor = vec4(vec3(0.0), 1.0);
}
#if 0
uniform mat4 mvpl;
const float w = 0.5;
@ -61,4 +74,5 @@ void main(void)
}
}
#endif

View File

@ -1,89 +1,10 @@
//uniform float far;
//uniform float near;
uniform float width;
uniform vec3 meshCenter;
//uniform mat4 modelViewMX;
//uniform mat4 prjMX;
varying vec3 normalVec;
varying float lightDepth;
varying vec3 viewVec;
varying vec3 lightVec;
//uniform mat4 mvpl;
varying vec4 pPos;
void main(void)
{
vec4 pPos = gl_Vertex;
pPos = gl_Vertex;
gl_Position = gl_ModelViewProjectionMatrix * pPos;
//gl_TexCoord[0] = gl_MultiTexCoord0;
vec4 lightPosition = gl_ModelViewMatrix * gl_LightSource[0].position;
// lighting is performed in eye space
vec4 ePos = gl_ModelViewMatrix * gl_Vertex;
vec4 eLight = gl_ModelViewMatrix * lightPosition; //lightPosition;
normalVec = gl_NormalMatrix * gl_Normal;
//lightVec = eLight.xyz - ePos.xyz;
viewVec = - ePos.xyz;
lightVec = eLight.xyz - ePos.xyz;
//Reproduce GL_LookAt behaviour
//create ortonormal basis for lightspace
vec3 newZ = normalize(lightPosition.xyz);
vec3 newX = normalize(cross(newZ, vec3(0.0, 0.80001, 0.0)));
vec3 newY = normalize(cross(newX, newZ));
mat4 toLightSpaceRot = mat4(
newX.x, newY.x, newZ.x, 0.0,
newX.y, newY.y, newZ.y, 0.0,
newX.z, newY.z, newZ.z, 0.0,
0.0, 0.0, 0.0, 1.0
);
//Perform parallel Ortographic projection
float nearP = - (width / 2.0);//meshCenter.z - (width / 2.0); //distance of Front clipping plane from VRP measured along VPN (a.k.a. lightDir)
float farP = (width / 2.0);//meshCenter.z + (width / 2.0);//distance of Back clipping plane from VRP measured along VPN (a.k.a. lightDir)
float leftP = meshCenter.x - width/2.0;
float rightP = meshCenter.x + width/2.0;
float bottomP = meshCenter.y - width/2.0;
float topP = meshCenter.y + width/2.0;
mat4 parallelViewProject = mat4(
2.0/(rightP-leftP), 0.0, 0.0, 0.0,
0.0, 2.0/(topP-bottomP), 0.0, 0.0,
0.0, 0.0, 2.0/(farP - nearP), 0.0,
-(rightP + leftP)/(rightP - leftP), -(topP + bottomP)/(topP-bottomP), -(farP + nearP)/(farP - nearP), 1.0
);
vec4 lightPos = parallelViewProject
* toLightSpaceRot
* gl_Vertex;
// glTexGen basically do:
// T = S * Pp * Vp * M * vertex
//
// vertex from local to world space (M)
// then to Light (projector) space (Vp)
// then projected (Pp)
// and at this point adjust to get texcoord from [-1, 1] to [0, 1] range (S)
mat4 texAdjTrSc = mat4(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
//vec4 prova = texAdjTrSc * lightPos;
lightDepth = lightPos.z;
gl_TexCoord[0] = texAdjTrSc * lightPos;
// we also need world space light vector
//lightVecDist = (lightDirection.xyz - gl_Vertex.xyz) * (1.0 / zFar);
//gl_Position = gl_ModelViewProjectionMatrix * pPos;
gl_Position = ftransform();
}

View File

@ -42,6 +42,7 @@ ShadowMapping::~ShadowMapping(){}
bool ShadowMapping::Init()
{
this->_texSize = 512;
compileLinkSM();
return true;
}
@ -54,43 +55,85 @@ void ShadowMapping::RunShader(MeshModel& m, GLArea* gla){
GLfloat g_mModelView[16];
GLfloat g_mProjection[16];
this->_texSize = bb.Diag();
(this->_texSize % 2) == 0 ? this->_texSize = this->_texSize + 2 : this->_texSize++;
glUseProgram(this->_depthShaderProgram);
this->_diag = bb.Diag();
/*glUseProgram(this->_depthShaderProgram);
GLint uLocWidth = glGetUniformLocation(this->_depthShaderProgram, "width");
GLint uLocMeshCenter = glGetUniformLocation(this->_depthShaderProgram, "meshCenter");
glUniform1f(uLocWidth, this->_texSize);
glUniform3f(uLocMeshCenter, center[0], center[1], center[2]);
*/
this->Setup();
this->Bind(m);
m.Render(vcg::GLW::DMFlat, vcg::GLW::CMPerFace, vcg::GLW::TMPerWedge);
this->GetQImage();
this->Unbind();
//vcg::Matrix44f mv, pr;
glUseProgram(0);
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(-(this->_diag/2),
this->_diag/2,
-(this->_diag/2),
this->_diag/2,
-(this->_diag/2),
this->_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]);
//glMultMatrixf(tm.transpose().V());
//glMultMatrixf(m.cm.Tr.transpose().V());
glGetFloatv(GL_MODELVIEW_MATRIX, g_mModelView);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(4.0, 4.0);
this->Setup();
this->Bind();
m.Render(vcg::GLW::DMSmooth, vcg::GLW::CMNone, vcg::GLW::TMNone);
glDisable(GL_POLYGON_OFFSET_FILL);
this->GetQImage();
this->Unbind();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
// glUseProgram(0);
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);
uLocWidth = glGetUniformLocation(this->_objectShaderProgram, "width");
uLocMeshCenter = glGetUniformLocation(this->_objectShaderProgram, "meshCenter");
glUniform1f(uLocWidth, gla->size().width());
glUniform3f(uLocMeshCenter, center[0], center[1], center[2]);
GLuint matrixLoc = glGetUniformLocation(this->_objectShaderProgram, "mvpl");
glUniformMatrix4fv(matrixLoc, 1, 0, mvpl.V());
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->_shadowMap);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
GLuint loc = glGetUniformLocation(this->_objectShaderProgram, "shadowMap");
glUniform1i(loc, 1);
glUniform1i(loc, 0);
m.Render(vcg::GLW::DMSmooth, vcg::GLW::CMPerVert, vcg::GLW::TMPerWedge);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDepthFunc((GLenum)depthFuncOld);
glUseProgram(0);
//glEnable (GL_BLEND);
//glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
int error = glGetError();
@ -106,15 +149,12 @@ bool ShadowMapping::Setup()
if (_initOk)
return true;
glGenFramebuffersEXT(1, &_fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
// depth buffer
glGenRenderbuffersEXT(1, &(this->_depth));
/*glGenRenderbuffersEXT(1, &(this->_depth));
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this->_depth);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, this->_texSize, this->_texSize);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, this->_depth);
*/
// color buffer
glGenTextures(1, &this->_shadowMap);
glBindTexture(GL_TEXTURE_2D, this->_shadowMap);
@ -124,11 +164,19 @@ bool ShadowMapping::Setup()
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);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
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);
//glGenerateMipmapEXT(GL_TEXTURE_2D);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_texSize, this->_texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->_shadowMap, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, this->_texSize, this->_texSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glGenFramebuffersEXT(1, &_fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, this->_shadowMap, 0);
//cosi specifichi che il colore non importa, che il fbo non ha niente sull'attachment colore
GLenum drawBuffers[] = {GL_NONE};
glDrawBuffersARB(1, drawBuffers);
int err = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
_initOk = (err == GL_FRAMEBUFFER_COMPLETE_EXT);
@ -136,7 +184,7 @@ bool ShadowMapping::Setup()
return _initOk;
}
void ShadowMapping::Bind(MeshModel &m)
void ShadowMapping::Bind()
{
assert(_initOk);
@ -144,7 +192,7 @@ void ShadowMapping::Bind(MeshModel &m)
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);
}
void ShadowMapping::Unbind()
@ -164,6 +212,29 @@ void ShadowMapping::GetQImage()
QImage img(this->_texSize, this->_texSize, QImage::Format_RGB32);
float *tempFBuf = new float[this->_texSize * this->_texSize *1 ];
float *tempFBufPtr = tempFBuf;
glBindTexture(GL_TEXTURE_2D, this->_shadowMap);
glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, tempFBufPtr);
for (int i = 0; i < this->_texSize; ++i) {
QRgb *scanLine = (QRgb*)img.scanLine(i);
for (int j = 0; j < this->_texSize; ++j) {
const unsigned char val = (unsigned char) (tempFBufPtr[0] * 255.0f);
scanLine[j] = qRgb(val, val, val);
tempFBufPtr ++;
}
}
delete[] tempFBuf;
img.mirrored().save("./_shadowMapTXT.png", "PNG");
}
/* void ShadowMapping::GetQImage()
{
if (!_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);
@ -178,6 +249,7 @@ void ShadowMapping::GetQImage()
delete[] tempBuf;
img.mirrored().save("./_shadowMapTXT.png", "PNG");
}
*/
bool ShadowMapping::compileLinkSM(){
GLenum err = glewInit();

View File

@ -49,14 +49,14 @@ private:
bool compileLinkSM();
//bool ClearBuffers();
bool Setup();
void Bind(MeshModel&);
void Bind();
void Unbind();
void GetQImage();
void printShaderInfoLog(GLuint);
void printProgramInfoLog(GLuint);
bool _initOk;
int _texSize;
int _texSize, _diag;
GLuint _shadowMap, _depth;
GLuint _fbo;
GLuint _depthShaderProgram, _objectShaderProgram;