Commit e2eca231 authored by Jan Möbius's avatar Jan Möbius
Browse files

New postprocessor pipeline


git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@17461 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 56b02b28
......@@ -52,6 +52,22 @@
* Interface for adding global image post processor functions. \ref postProcessorInterfacePage
*/
struct PostProcessorInput
{
PostProcessorInput(GLuint colTex = 0,
GLuint depthTex = 0,
int width = 0,
int height = 0)
: colorTex_(colTex), depthTex_(depthTex), width(width), height(height) {}
GLuint colorTex_;
GLuint depthTex_;
int width, height;
};
/** \brief Interface to add global image post processor functions from within plugins.
*
* \ref postProcessorInterfacePage "Detailed description"
......@@ -72,7 +88,7 @@ class PostProcessorInterface {
/** \brief post processor function
*
*/
virtual void postProcess(ACG::GLState* _glState) {};
virtual void postProcess(ACG::GLState* _glState, const PostProcessorInput& _input, GLuint _targetFBO = 0) {};
/** \brief announce name for the postProcessor function
*
......
......@@ -165,7 +165,8 @@ glViewer::glViewer( QGraphicsScene* _scene,
flyAnimationOrthogonal_(0),
flyAngle_(0.0),
currentAnimationPos_(0.0),
flyMoveBack_(false)
flyMoveBack_(false),
sceneTexReadBackWidth_(0), sceneTexReadBackHeight_(0)
{
// widget stuff
......@@ -638,6 +639,11 @@ void glViewer::drawScene()
//
// fbo.bind();
updatePostProcessingBufs(glstate_->viewport_width(),glstate_->viewport_height());
// glBindFramebuffer(GL_FRAMEBUFFER, postProcessFBO_);
// Check if we use build in default renderer
if ( renderManager().activeId( properties_.viewerId() ) == 0 ) {
drawScene_mono();
......@@ -645,11 +651,67 @@ void glViewer::drawScene()
renderManager().active( properties_.viewerId() )->plugin->render(glstate_,properties_);
}
// glBindFramebuffer(GL_FRAMEBUFFER, 0);
// =================================================================================
// Post-Processing pipeline
readBackBuffer(glstate_);
int numPostProcessors = postProcessorManager().numActive(properties_.viewerId());
// // DEBUG testing post processor chain
// if (numPostProcessors == 1)
// {
// postProcessorManager().append("Grayscale Postprocessor Plugin", properties_.viewerId());
// postProcessorManager().append("Red Postprocessor Plugin", properties_.viewerId());
//
// numPostProcessors += 2;
// }
// 1st post processing source: back buffer
int postProcSrc = 1;
PostProcessorInput postProcInput;
postProcInput.colorTex_ = sceneTexReadBack_.id();
postProcInput.depthTex_ = depthTexReadBack_.id();
postProcInput.width = sceneTexReadBackWidth_;
postProcInput.height = sceneTexReadBackHeight_;
// execute post processing chain with 2 FBOs
for (int i = 0; i < numPostProcessors; ++i) {
int postProcTarget = 1 - postProcSrc;
if ( postProcessorManager().activeId( properties_.viewerId() ) != 0 ) {
postProcessorManager().active( properties_.viewerId() )->plugin->postProcess(glstate_);
GLuint targetFBO = postProcessFBO_[postProcTarget].getFboID();
// write to back buffer in last step
if (i + 1 == numPostProcessors)
targetFBO = 0;
// apply post processor
PostProcessorInfo* proc = postProcessorManager().active( properties_.viewerId(), i );
if (proc && proc->plugin)
proc->plugin->postProcess(glstate_, postProcInput, targetFBO);
// swap target/source fbo
postProcSrc = postProcTarget;
postProcInput.colorTex_ = postProcessFBO_[postProcSrc].getAttachment(GL_COLOR_ATTACHMENT0);
postProcInput.depthTex_ = postProcessFBO_[postProcSrc].getAttachment(GL_DEPTH_ATTACHMENT);
}
// =================================================================================
// unbind vbo for qt log window
glBindBuffer(GL_ARRAY_BUFFER, 0);
// fbo.release();
//
// QRect blitRect(0,0,glstate_->viewport_width(),glstate_->viewport_height());
......@@ -2330,6 +2392,88 @@ void glViewer::strafeRight() {
}
}
void glViewer::readBackBuffer(ACG::GLState* _glstate)
{
int width, height, x, y;
_glstate->get_viewport(x, y, width, height);
if (!sceneTexReadBack_.is_valid())
{
// create r8g8b8a8 color texture
sceneTexReadBack_.enable();
sceneTexReadBack_.bind();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
sceneTexReadBackWidth_ = width;
sceneTexReadBackHeight_ = height;
}
if (!depthTexReadBack_.is_valid())
{
// create D24S8 texture
depthTexReadBack_.enable();
depthTexReadBack_.bind();
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, width, height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
sceneTexReadBackWidth_ = width;
sceneTexReadBackHeight_ = height;
}
// Resize if already exists
if (width != sceneTexReadBackWidth_ || height != sceneTexReadBackHeight_)
{
sceneTexReadBack_.bind();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
depthTexReadBack_.bind();
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
sceneTexReadBackWidth_ = width;
sceneTexReadBackHeight_ = height;
}
// read back buffer
sceneTexReadBack_.bind();
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, width , height, 0);
depthTexReadBack_.bind();
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, x, y, width , height, 0);
}
void glViewer::updatePostProcessingBufs(int _width, int _height)
{
for (int i = 0; i < 2; ++i)
{
if (!postProcessFBO_[i].getFboID())
{
postProcessFBO_[i].init();
postProcessFBO_[i].attachTexture2D(GL_COLOR_ATTACHMENT0, _width, _height, GL_RGBA, GL_RGBA, GL_CLAMP, GL_NEAREST, GL_NEAREST);
postProcessFBO_[i].attachTexture2DDepth(_width, _height);
}
else
postProcessFBO_[i].resize(_width, _height);
}
}
//=============================================================================
//=============================================================================
......@@ -58,6 +58,7 @@
#include <OpenFlipper/common/ViewerProperties.hh>
#include <ACG/GL/GLState.hh>
#include <ACG/GL/FBO.hh>
#include <ACG/Scenegraph/SceneGraph.hh>
#include <ACG/QtWidgets/QtSceneGraphWidget.hh>
......@@ -100,6 +101,7 @@ class QSplitter;
class QTimer;
class QImage;
class QSocketNotifier;
struct PostProcessorInput;
//== NAMESPACES ===============================================================
......@@ -1027,6 +1029,37 @@ private:
void flyAnimationOrthogonalFinished();
/** @} */
//===========================================================================
/** @name Post Processing
* @{ */
//===========================================================================
private:
/// source/target fbo
ACG::FBO postProcessFBO_[2];
/// scene texture (read back from back-buffer)
ACG::Texture2D sceneTexReadBack_;
ACG::Texture2D depthTexReadBack_;
int sceneTexReadBackWidth_, sceneTexReadBackHeight_;
void readBackBuffer(ACG::GLState* _glstate);
/** \brief Adjust size of post processor FBO and attachments
*
*/
void updatePostProcessingBufs(int width, int height);
/** @} */
};
......
include (plugin)
openflipper_plugin ( )
openflipper_plugin ( INSTALLDATA Shaders )
......@@ -50,148 +50,80 @@
#include <iostream>
#include <ACG/GL/GLState.hh>
#include <ACG/GL/ScreenQuad.hh>
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
#include <OpenFlipper/common/GlobalOptions.hh>
PostProcessorDepthImagePlugin::PostProcessorDepthImagePlugin() :
depthStencilTextureBufferWidth_(0),
depthStencilTextureBufferHeight_(0)
PostProcessorDepthImagePlugin::PostProcessorDepthImagePlugin()
: shader_(0)
{
}
QString PostProcessorDepthImagePlugin::postProcessorName() {
return QString("Show Depth Image");
}
void PostProcessorDepthImagePlugin::updateDepthStencilTextureBuffer(ACG::GLState* _glstate) {
if ( !ACG::checkExtensionSupported("GL_ARB_texture_rectangle") ) {
std::cerr << "GL_ARB_texture_rectangle not supported! " << std::endl;
return;
}
int vp_l, vp_b, vp_w, vp_h;
_glstate->get_viewport (vp_l, vp_b, vp_w, vp_h);
// Does depth stencil texture exist?
if (!pDepthStencilTexture_.is_valid()) {
// ======================================================================================================
// creating an 24-bit depth + 8-bit stencil texture
// ======================================================================================================
pDepthStencilTexture_.enable();
pDepthStencilTexture_.bind();
GLenum texTarget = GL_TEXTURE_2D;
GLenum texInternalFormat = GL_DEPTH24_STENCIL8_EXT;
GLenum texFormat = GL_DEPTH_STENCIL_EXT;
GLenum texType = GL_UNSIGNED_INT_24_8_EXT;
GLenum texFilterMode = GL_NEAREST;
glTexImage2D(texTarget, 0, texInternalFormat, vp_w, vp_h, 0, texFormat, texType, NULL);
glTexParameterf(texTarget, GL_TEXTURE_MIN_FILTER, texFilterMode);
glTexParameterf(texTarget, GL_TEXTURE_MAG_FILTER, texFilterMode);
glTexParameterf(texTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(texTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(texTarget, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
}
// Resize target texture
if (_glstate->viewport_width() != depthStencilTextureBufferWidth_ || _glstate->viewport_height() != depthStencilTextureBufferHeight_) {
// Depth stencil texture
pDepthStencilTexture_.bind();
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, _glstate->viewport_width(), _glstate->viewport_height(), 0,
GL_RGB, GL_UNSIGNED_BYTE, 0);
ACG::GLState::bindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
depthStencilTextureBufferWidth_ = _glstate->viewport_width();
depthStencilTextureBufferHeight_ = _glstate->viewport_height();
}
PostProcessorDepthImagePlugin::~PostProcessorDepthImagePlugin()
{
delete shader_;
}
QString PostProcessorDepthImagePlugin::postProcessorName() {
return QString("Show Depth Image");
}
void PostProcessorDepthImagePlugin::postProcess(ACG::GLState* _glstate) {
void PostProcessorDepthImagePlugin::postProcess(ACG::GLState* _glstate, const PostProcessorInput& _input, GLuint _targetFBO) {
// ======================================================================================================
// Adjust buffer to correct size
// Load shader if needed
// ======================================================================================================
updateDepthStencilTextureBuffer(_glstate);
if (!shader_)
shader_ = GLSL::loadProgram("ShowDepth/screenquad.glsl", "ShowDepth/depth.glsl");
// ======================================================================================================
// Get current viewport size
// Bind input texture
// ======================================================================================================
int vp_l, vp_b, vp_w, vp_h;
_glstate->get_viewport(vp_l, vp_b, vp_w, vp_h);
// ======================================================================================================
// Bind depth Stencil texture
// ======================================================================================================
pDepthStencilTexture_.enable();
pDepthStencilTexture_.bind();
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _input.depthTex_);
// ======================================================================================================
// Copy depth component of rendered image to texture
// Bind output FBO
// ======================================================================================================
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, vp_l, vp_b, vp_w , vp_h, 0);
glBindFramebuffer(GL_FRAMEBUFFER, _targetFBO);
// ======================================================================================================
// Render plain textured
// Clear rendering buffer
// ======================================================================================================
ACG::GLState::disable(GL_LIGHTING);
ACG::GLState::disable(GL_COLOR_MATERIAL);
ACG::GLState::disable(GL_DEPTH_TEST);
_glstate->clearBuffers();
// ======================================================================================================
// Setup orthogonal projection
// Setup render states
// ======================================================================================================
_glstate->push_projection_matrix();
_glstate->push_modelview_matrix();
_glstate->reset_projection();
_glstate->reset_modelview();
// Setup orthogonal projection (remember that we are in a viewport of the current glstate)
_glstate->ortho(0, vp_w, 0, vp_h, 0, 1);
glDepthMask(1);
glColorMask(1,1,1,1);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
// ======================================================================================================
// Clear rendering buffer
// Setup shader
// ======================================================================================================
_glstate->clearBuffers();
// ======================================================================================================
// Render a simple quad (rest is done by the texture)
// ======================================================================================================
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2i(0, 0);
glTexCoord2f(1.0f, 0.0f);
glVertex2i(vp_w, 0);
glTexCoord2f(1.0f, 1.0f);
glVertex2i(vp_w, vp_h);
glTexCoord2f(0.0f, 1.0f);
glVertex2i(0, vp_h);
glEnd();
// Disable depth stencil buffer
pDepthStencilTexture_.disable();
shader_->use();
shader_->setUniform("textureSampler", 0);
// ======================================================================================================
// Reset projection and modelview
// Execute
// ======================================================================================================
_glstate->pop_projection_matrix();
_glstate->pop_modelview_matrix();
ACG::ScreenQuad::draw(shader_);
shader_->disable();
}
#if QT_VERSION < 0x050000
......
......@@ -59,7 +59,8 @@ class PostProcessorDepthImagePlugin : public QObject, BaseInterface, PostProcess
#endif
public:
PostProcessorDepthImagePlugin();
PostProcessorDepthImagePlugin();
~PostProcessorDepthImagePlugin();
public :
QString name() { return (QString("Depth Image Postprocessor Plugin")); };
......@@ -71,21 +72,13 @@ class PostProcessorDepthImagePlugin : public QObject, BaseInterface, PostProcess
private slots:
void updateDepthStencilTextureBuffer(ACG::GLState* _glstate);
void postProcess(ACG::GLState* _glstate);
void postProcess(ACG::GLState* _glstate, const PostProcessorInput& _input, GLuint _targetFBO);
QString postProcessorName();
private:
/// depthStencil texture buffer
ACG::Texture2D pDepthStencilTexture_;
/// Current width of the depthStencil texture buffer
int depthStencilTextureBufferWidth_;
/// Current height of the depthStencil texture buffer
int depthStencilTextureBufferHeight_;
/// shader
GLSL::Program* shader_;
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment