mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-17 10:04:38 +00:00
350 lines
11 KiB
C++
350 lines
11 KiB
C++
/****************************************************************************
|
|
* MeshLab o o *
|
|
* An extendible mesh processor o o *
|
|
* _ O _ *
|
|
* Copyright(C) 2005, 2006 \/)\/ *
|
|
* 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 "ssao.h"
|
|
|
|
#include <common/globals.h>
|
|
|
|
SSAO::SSAO(float radius):DecorateShader()
|
|
{
|
|
this->_radius = radius;
|
|
|
|
this->_depth = 0;
|
|
|
|
this->_color1 = 0;
|
|
this->_normalMapFrag = 0;
|
|
this->_normalMapVert = 0;
|
|
this->_normalMapShaderProgram = 0;
|
|
|
|
this->_depthMap = 0;
|
|
|
|
this->_color2= 0;
|
|
this->_ssaoVert = 0;
|
|
this->_ssaoFrag = 0;
|
|
this->_ssaoShaderProgram = 0;
|
|
|
|
this->_blurVert = 0;
|
|
this->_blurFrag = 0;
|
|
this->_blurShaderProgram = 0;
|
|
this->_fbo = 0;
|
|
this->_fbo2 = 0;
|
|
}
|
|
|
|
SSAO::~SSAO(){
|
|
glDetachShader(this->_normalMapShaderProgram, this->_normalMapVert);
|
|
glDetachShader(this->_normalMapShaderProgram, this->_normalMapFrag);
|
|
|
|
glDeleteShader(this->_normalMapVert);
|
|
glDeleteShader(this->_normalMapFrag);
|
|
glDeleteProgram(this->_normalMapShaderProgram);
|
|
|
|
glDetachShader(this->_ssaoShaderProgram, this->_ssaoVert);
|
|
glDetachShader(this->_ssaoShaderProgram, this->_ssaoFrag);
|
|
|
|
glDeleteShader(this->_ssaoVert);
|
|
glDeleteShader(this->_ssaoFrag);
|
|
glDeleteProgram(this->_ssaoShaderProgram);
|
|
|
|
glDetachShader(this->_blurShaderProgram, this->_blurVert);
|
|
glDetachShader(this->_blurShaderProgram, this->_blurFrag);
|
|
|
|
glDeleteShader(this->_blurVert);
|
|
glDeleteShader(this->_blurFrag);
|
|
glDeleteProgram(this->_blurShaderProgram);
|
|
|
|
glDeleteTextures(1, &(this->_color1));
|
|
glDeleteTextures(1, &(this->_depthMap));
|
|
|
|
glDeleteFramebuffers(1, &(this->_depth));
|
|
glDeleteTextures(1, &(this->_color2));
|
|
glDeleteTextures(1, &(this->_color2));
|
|
|
|
glDeleteFramebuffers(1, &_fbo);
|
|
glDeleteFramebuffers(1, &_fbo2);
|
|
}
|
|
|
|
bool SSAO::init()
|
|
{
|
|
if(!this->initGlew() || !this->initSetup())
|
|
return false;
|
|
|
|
if(!compileAndLink(
|
|
this->_ssaoShaderProgram,
|
|
this->_ssaoVert,
|
|
this->_ssaoFrag,
|
|
meshlab::defaultShadersPath() + "/decorate_shadow/ssao/ssao") ||
|
|
!compileAndLink(
|
|
this->_normalMapShaderProgram,
|
|
this->_normalMapVert,
|
|
this->_normalMapFrag,
|
|
meshlab::defaultShadersPath() + "/decorate_shadow/ssao/normalMap") ||
|
|
!compileAndLink(
|
|
this->_blurShaderProgram,
|
|
this->_blurVert,
|
|
this->_blurFrag,
|
|
meshlab::defaultShadersPath() + "/decorate_shadow/ssao/blur"))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void SSAO::runShader(MeshDocument& md, GLArea* gla)
|
|
{
|
|
|
|
/***********************************************************/
|
|
//NORMAL MAP and DEPTH MAP generation
|
|
/***********************************************************/
|
|
MLSceneGLSharedDataContext* ctx = NULL;
|
|
if ((gla == NULL) || (gla->mvc() == NULL))
|
|
return;
|
|
ctx = gla->mvc()->sharedDataContext();
|
|
if (ctx == NULL)
|
|
return;
|
|
|
|
this->bind();
|
|
glUseProgram(this->_normalMapShaderProgram);
|
|
|
|
vcg::Matrix44f mProj, mInverseProj;
|
|
glMatrixMode(GL_PROJECTION);
|
|
glGetFloatv(GL_PROJECTION_MATRIX, mProj.V());
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
mProj.transposeInPlace();
|
|
mInverseProj = vcg::Inverse(mProj);
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
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);
|
|
}
|
|
}
|
|
glUseProgram(0);
|
|
|
|
/***********************************************************/
|
|
//SSAO PASS
|
|
/***********************************************************/
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fbo2);
|
|
glUseProgram(this->_ssaoShaderProgram);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, this->_noise);
|
|
GLuint noiseloc = glGetUniformLocation(this->_ssaoShaderProgram, "rnm");
|
|
glUniform1i(noiseloc, 0);
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glBindTexture(GL_TEXTURE_2D, this->_color1);
|
|
GLuint loc = glGetUniformLocation(this->_ssaoShaderProgram, "normalMap");
|
|
glUniform1i(loc, 1);
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, this->_depthMap);
|
|
loc = glGetUniformLocation(this->_ssaoShaderProgram, "depthMap");
|
|
glUniform1i(loc, 2);
|
|
|
|
GLuint radiusLoc = glGetUniformLocation(this->_ssaoShaderProgram, "rad");
|
|
glUniform1f(radiusLoc, this->_radius);
|
|
|
|
GLuint matrixLoc = glGetUniformLocation(this->_ssaoShaderProgram, "proj");
|
|
glUniformMatrix4fv(matrixLoc, 1, 0, mProj.transpose().V());
|
|
|
|
GLuint invMatrixLoc = glGetUniformLocation(this->_ssaoShaderProgram, "invProj");
|
|
glUniformMatrix4fv(invMatrixLoc, 1, 0, mInverseProj.transpose().V());
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
glVertex3f(-1.0f, -1.0f, 0.0f);
|
|
glVertex3f( 1.0f, -1.0f, 0.0f);
|
|
glVertex3f(-1.0f, 1.0f, 0.0f);
|
|
glVertex3f( 1.0f, 1.0f, 0.0f);
|
|
glEnd();
|
|
glUseProgram(0);
|
|
|
|
/***********************************************************/
|
|
//BLURRING horizontal
|
|
/***********************************************************/
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
|
|
glUseProgram(this->_blurShaderProgram);
|
|
|
|
float blur_coef(0.8f);
|
|
GLfloat scale = 1/(this->_texW * blur_coef);
|
|
|
|
GLuint scaleLoc = glGetUniformLocation(this->_blurShaderProgram, "scale");
|
|
glUniform2f(scaleLoc, scale, 0.0);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, this->_color2);
|
|
loc = glGetUniformLocation(this->_blurShaderProgram, "scene");
|
|
glUniform1i(loc, 0);
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
glVertex3f(-1.0f, -1.0f, 0.0f);
|
|
glVertex3f( 1.0f, -1.0f, 0.0f);
|
|
glVertex3f(-1.0f, 1.0f, 0.0f);
|
|
glVertex3f( 1.0f, 1.0f, 0.0f);
|
|
glEnd();
|
|
|
|
/***********************************************************/
|
|
//BLURRING vertical
|
|
/***********************************************************/
|
|
this->unbind();
|
|
glUniform2f(scaleLoc, 0.0, scale);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glBindTexture(GL_TEXTURE_2D, this->_color1);
|
|
loc = glGetUniformLocation(this->_blurShaderProgram, "scene");
|
|
glUniform1i(loc, 0);
|
|
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
glVertex3f(-1.0f, -1.0f, 0.0f);
|
|
glVertex3f( 1.0f, -1.0f, 0.0f);
|
|
glVertex3f(-1.0f, 1.0f, 0.0f);
|
|
glVertex3f( 1.0f, 1.0f, 0.0f);
|
|
glEnd();
|
|
|
|
glUseProgram(0);
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glDisable(GL_BLEND);
|
|
}
|
|
|
|
bool SSAO::setup()
|
|
{
|
|
if (!GLEW_EXT_framebuffer_object) {
|
|
qWarning("FBO not supported!");
|
|
return false;
|
|
}
|
|
|
|
if (_initOk)
|
|
return true;
|
|
|
|
//genero i 2 framebuffer object che mi servono.
|
|
glGenFramebuffers(1, &_fbo);
|
|
glGenFramebuffers(1, &_fbo2);
|
|
|
|
//attacco il primo...adesso le modifiche andranno a modificare solo _fbo
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
|
|
|
|
//Generates first color texture
|
|
this->genColorTextureEXT(this->_color1, GL_COLOR_ATTACHMENT0);
|
|
|
|
this->genDepthMapTexture24(this->_depthMap, false);
|
|
|
|
GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0};
|
|
|
|
glDrawBuffersARB(0, drawBuffers);
|
|
|
|
int err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
_initOk = (err == GL_FRAMEBUFFER_COMPLETE);
|
|
|
|
if(!this->_initOk)
|
|
return this->_initOk;
|
|
|
|
//attacco il secondo fbo...adesso le modifiche andranno a modificare solo _fbo2
|
|
glBindFramebuffer(GL_FRAMEBUFFER, _fbo2);
|
|
|
|
//Generates first color texture
|
|
this->genColorTextureEXT(this->_color2, GL_COLOR_ATTACHMENT0);
|
|
|
|
//Generates render buffer for depth attachment
|
|
this->genDepthRenderBufferEXT(this->_depth);
|
|
|
|
GLenum drawBuffers2[] = {GL_COLOR_ATTACHMENT0};
|
|
|
|
glDrawBuffersARB(0, drawBuffers2);
|
|
|
|
this->loadNoiseTxt();
|
|
|
|
err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
_initOk = (err == GL_FRAMEBUFFER_COMPLETE);
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
return _initOk;
|
|
}
|
|
|
|
bool SSAO::loadNoiseTxt(){
|
|
|
|
QImage image = QImage();
|
|
QString textureName = QString(":/rand.png");
|
|
if (QFile(textureName).exists())
|
|
{
|
|
image = QImage(textureName);
|
|
noiseWidth=image.width();
|
|
noiseHeight=image.height();
|
|
|
|
QImage tmpGL = QGLWidget::convertToGLFormat(image);
|
|
image = QImage(tmpGL);
|
|
}
|
|
else {
|
|
qDebug("Warning failed to load noise texture!");
|
|
assert(0);
|
|
return false;
|
|
}
|
|
|
|
// Creates The Texture
|
|
glGenTextures(1, &(this->_noise));
|
|
glBindTexture(GL_TEXTURE_2D, this->_noise);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
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_RGB, noiseWidth , noiseHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image.bits());
|
|
|
|
return true;
|
|
}
|
|
|
|
void SSAO::printNoiseTxt(){
|
|
QImage img(noiseWidth , noiseHeight, QImage::Format_RGB32);
|
|
|
|
unsigned char *tempBuf = new unsigned char[noiseWidth * noiseHeight * 3];
|
|
unsigned char *tempBufPtr = tempBuf;
|
|
glBindTexture(GL_TEXTURE_2D, this->_noise);
|
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, tempBufPtr);
|
|
for (int i = 0; i < noiseWidth; ++i) {
|
|
QRgb *scanLine = (QRgb*)img.scanLine(i);
|
|
for (int j = 0; j < noiseHeight; ++j) {
|
|
scanLine[j] = qRgb(tempBufPtr[0], tempBufPtr[1], tempBufPtr[2]);
|
|
tempBufPtr += 3;
|
|
}
|
|
}
|
|
|
|
delete[] tempBuf;
|
|
|
|
img.mirrored().save("_noise.png", "PNG");
|
|
}
|