mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-20 03:16:10 +00:00
224 lines
7.3 KiB
C++
224 lines
7.3 KiB
C++
/****************************************************************************
|
|
* MeshLab o o *
|
|
* A versatile mesh processing toolbox o o *
|
|
* _ O _ *
|
|
* Copyright(C) 2005 \/)\/ *
|
|
* Visual Computing Lab /\/| *
|
|
* ISTI - Italian National Research Council | *
|
|
* \ *
|
|
* All rights reserved. *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
|
* for more details. *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
#include <meshlab/glarea.h>
|
|
#include "decorate_shader.h"
|
|
#include "shadow_mapping.h"
|
|
#include <common/pluginmanager.h>
|
|
|
|
|
|
ShadowMapping::ShadowMapping(float intensity):DecorateShader()
|
|
{
|
|
this->_intensity=intensity;
|
|
this->_shadowMappingVert = 0;
|
|
this->_shadowMappingFrag = 0;
|
|
this->_shadowMappingProgram = 0;
|
|
this->_fbo = 0;
|
|
}
|
|
|
|
ShadowMapping::~ShadowMapping(){
|
|
glDetachShader(this->_shadowMappingProgram, this->_shadowMappingVert);
|
|
glDetachShader(this->_shadowMappingProgram, this->_shadowMappingFrag);
|
|
|
|
glDeleteShader(this->_shadowMappingVert);
|
|
glDeleteShader(this->_shadowMappingFrag);
|
|
glDeleteProgram(this->_shadowMappingProgram);
|
|
|
|
glDeleteTextures(1, &(this->_shadowMap));
|
|
|
|
glDeleteFramebuffersEXT(1, &_fbo);
|
|
}
|
|
|
|
bool ShadowMapping::init()
|
|
{
|
|
if(!this->initGlew() || !this->initSetup())
|
|
return false;
|
|
|
|
return compileAndLink(
|
|
this->_shadowMappingProgram,
|
|
this->_shadowMappingVert,
|
|
this->_shadowMappingFrag,
|
|
PluginManager::getBaseDirPath().append(QString("/shaders/decorate_shadow/sm/object")));
|
|
}
|
|
|
|
void ShadowMapping::renderingFromLightSetup(MeshDocument& md, GLArea* gla){
|
|
Box3m bb = md.bbox();
|
|
Point3m center = bb.Center();
|
|
Scalarm 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);
|
|
|
|
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]);
|
|
}
|
|
|
|
|
|
void ShadowMapping::renderingFromLightUnsetup(){
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
}
|
|
|
|
void ShadowMapping::runShader(MeshDocument& md, GLArea* gla){
|
|
GLfloat g_mModelView[16];
|
|
GLfloat g_mProjection[16];
|
|
|
|
MLSceneGLSharedDataContext* ctx = NULL;
|
|
if ((gla == NULL) || (gla->mvc() == NULL))
|
|
return;
|
|
ctx = gla->mvc()->sharedDataContext();
|
|
if (ctx == NULL)
|
|
return;
|
|
|
|
this->renderingFromLightSetup(md, gla);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glGetFloatv(GL_PROJECTION_MATRIX, g_mProjection);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, g_mModelView);
|
|
|
|
/***********************************************************/
|
|
//SHADOW MAP Generation
|
|
/***********************************************************/
|
|
|
|
//first rendering to get shadowMap from the light point of view
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
glPolygonOffset(4.0, 4.0);
|
|
|
|
//binding the FBO
|
|
this->bind();
|
|
MLRenderingData dt;
|
|
MLRenderingData::RendAtts atts;
|
|
atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
|
|
atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true;
|
|
atts[MLRenderingData::ATT_NAMES::ATT_FACENORMAL] = true;
|
|
dt.set(MLRenderingData::PR_SOLID, atts);
|
|
|
|
foreach(MeshModel *m, md.meshList)
|
|
{
|
|
if ((m != NULL) && (m->visible))
|
|
{
|
|
ctx->drawAllocatedAttributesSubset(m->id(), gla->context(), dt);
|
|
}
|
|
}
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
|
//unbinding the FBO
|
|
this->unbind();
|
|
|
|
this->renderingFromLightUnsetup();
|
|
|
|
/***********************************************************/
|
|
//SHADOW MAP Generation finished
|
|
/***********************************************************/
|
|
|
|
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->_shadowMappingProgram);
|
|
|
|
GLuint matrixLoc = glGetUniformLocation(this->_shadowMappingProgram, "mvpl");
|
|
glUniformMatrix4fv(matrixLoc, 1, 0, mvpl.V());
|
|
|
|
GLuint shadowIntensityLoc = glGetUniformLocation(this->_shadowMappingProgram, "shadowIntensity");
|
|
glUniform1f(shadowIntensityLoc, this->_intensity);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, this->_shadowMap);
|
|
|
|
GLuint loc = glGetUniformLocation(this->_shadowMappingProgram, "shadowMap");
|
|
glUniform1i(loc, 0);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
foreach(MeshModel *m, md.meshList)
|
|
{
|
|
if ((m != NULL) && (m->visible))
|
|
{
|
|
ctx->drawAllocatedAttributesSubset(m->id(), gla->context(),dt);
|
|
}
|
|
}
|
|
glDisable(GL_BLEND);
|
|
glDepthFunc((GLenum)depthFuncOld);
|
|
glUseProgram(0);
|
|
}
|
|
|
|
bool ShadowMapping::setup()
|
|
{
|
|
if (!GLEW_EXT_framebuffer_object) {
|
|
qWarning("FBO not supported!");
|
|
return false;
|
|
}
|
|
|
|
if (_initOk)
|
|
return true;
|
|
|
|
glGenFramebuffersEXT(1, &_fbo);
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _fbo);
|
|
|
|
this->genDepthMapTexture24(this->_shadowMap, true);
|
|
|
|
//we don't need a color attachment
|
|
GLenum drawBuffers[] = {GL_NONE};
|
|
glDrawBuffersARB(1, drawBuffers);
|
|
|
|
glReadBuffer(GL_NONE);
|
|
|
|
//checks for fbo creation errors
|
|
int err = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
|
_initOk = (err == GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
return _initOk;
|
|
}
|