mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-15 00:54:38 +00:00
182 lines
5.8 KiB
C++
182 lines
5.8 KiB
C++
/****************************************************************************
|
|
* MeshLab o o *
|
|
* A versatile mesh processing toolbox o o *
|
|
* _ O _ *
|
|
* Copyright(C) 2005-2008 \/)\/ *
|
|
* 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 "rfx_rendertarget.h"
|
|
|
|
RfxRenderTarget::RfxRenderTarget(const QString& rtName)
|
|
{
|
|
name = rtName;
|
|
width = 0;
|
|
height = 0;
|
|
fbo = 0;
|
|
depTex = 0;
|
|
colTex = 0;
|
|
mipmaps = false;
|
|
vportdim = false;
|
|
initOk = false;
|
|
}
|
|
|
|
RfxRenderTarget::~RfxRenderTarget()
|
|
{
|
|
if (initOk) {
|
|
glDeleteFramebuffersEXT(1, &fbo);
|
|
glDeleteRenderbuffersEXT(1, &depTex);
|
|
glDeleteTextures(1, &colTex);
|
|
}
|
|
}
|
|
|
|
void RfxRenderTarget::SetClear(int pass, float depthClear, float *colorClear)
|
|
{
|
|
passOptions[pass].clearMask = 0;
|
|
passOptions[pass].colorClear = false;
|
|
passOptions[pass].depthClear = false;
|
|
|
|
// valid depth clear values are [0, 1]
|
|
// -1.0 disable depth clear
|
|
if (depthClear != -1.0) {
|
|
passOptions[pass].depthClear = true;
|
|
|
|
passOptions[pass].depthClearVal = depthClear;
|
|
passOptions[pass].clearMask |= GL_DEPTH_BUFFER_BIT;
|
|
}
|
|
|
|
// color should be a 4-elements array.
|
|
// NULL disable color clear
|
|
if (colorClear != NULL) {
|
|
passOptions[pass].colorClear = true;
|
|
|
|
passOptions[pass].colorClearVal[0] = colorClear[0];
|
|
passOptions[pass].colorClearVal[1] = colorClear[1];
|
|
passOptions[pass].colorClearVal[2] = colorClear[2];
|
|
passOptions[pass].colorClearVal[3] = colorClear[3];
|
|
passOptions[pass].clearMask |= GL_COLOR_BUFFER_BIT;
|
|
}
|
|
}
|
|
|
|
bool RfxRenderTarget::Setup(int pass)
|
|
{
|
|
if (!GLEW_EXT_framebuffer_object) {
|
|
qWarning("FBO not supported!");
|
|
return false;
|
|
}
|
|
|
|
if (initOk)
|
|
return true;
|
|
|
|
glGenFramebuffersEXT(1, &fbo);
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
|
|
|
// if "use viewport dimensions" at this point we have a gl context
|
|
if (vportdim) {
|
|
GLfloat dims[4];
|
|
glGetFloatv(GL_VIEWPORT, dims);
|
|
width = (int)dims[2];
|
|
height = (int)dims[3];
|
|
}
|
|
|
|
// depth buffer
|
|
glGenRenderbuffersEXT(1, &depTex);
|
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depTex);
|
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
|
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depTex);
|
|
|
|
// color buffer
|
|
glGenTextures(1, &colTex);
|
|
glBindTexture(GL_TEXTURE_2D, colTex);
|
|
|
|
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, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, colTex, 0);
|
|
|
|
// set texture state based on the first uniform that will use RT
|
|
QList<int> k = passStates.keys();
|
|
for (int i = 0; i < k.size(); ++i) {
|
|
if (k.at(i) > pass) {
|
|
foreach (RfxState *s, passStates.value(i))
|
|
s->SetEnvironment(GL_TEXTURE_2D);
|
|
}
|
|
}
|
|
|
|
initOk = (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
return initOk;
|
|
}
|
|
|
|
void RfxRenderTarget::Bind(int pass)
|
|
{
|
|
assert(initOk);
|
|
|
|
bool colClear = passOptions.value(pass).colorClear;
|
|
bool depClear = passOptions.value(pass).depthClear;
|
|
|
|
if (colClear) {
|
|
const float *cols = passOptions.value(pass).colorClearVal;
|
|
glClearColor(cols[0], cols[1], cols[2], cols[3]);
|
|
}
|
|
|
|
if (depClear)
|
|
glClearDepth(passOptions.value(pass).depthClearVal);
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
|
|
|
glPushAttrib(GL_VIEWPORT_BIT);
|
|
glViewport(0, 0, width, height);
|
|
|
|
if (colClear || depClear)
|
|
glClear(passOptions.value(pass).clearMask);
|
|
}
|
|
|
|
void RfxRenderTarget::Unbind()
|
|
{
|
|
if (!initOk)
|
|
return;
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
glPopAttrib();
|
|
}
|
|
|
|
QImage RfxRenderTarget::GetQImage()
|
|
{
|
|
if (!initOk)
|
|
return QImage();
|
|
|
|
QImage img(width, height, QImage::Format_RGB32);
|
|
|
|
unsigned char *tempBuf = new unsigned char[width * height * 3];
|
|
unsigned char *tempBufPtr = tempBuf;
|
|
glBindTexture(GL_TEXTURE_2D, colTex);
|
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, tempBufPtr);
|
|
for (int i = 0; i < height; ++i) {
|
|
QRgb *scanLine = (QRgb*)img.scanLine(i);
|
|
for (int j = 0; j < width; ++j) {
|
|
scanLine[j] = qRgb(tempBufPtr[0], tempBufPtr[1], tempBufPtr[2]);
|
|
tempBufPtr += 3;
|
|
}
|
|
}
|
|
delete[] tempBuf;
|
|
|
|
return img.mirrored();
|
|
}
|