45 #include <ACG/GL/acg_glew.hh> 46 #include <ACG/GL/GLError.hh> 47 #include <ACG/GL/AntiAliasing.hh> 49 #include <OpenFlipper/common/RendererInfo.hh> 52 #include "PostProcessing.hh" 57 PostProcessing::PostProcessing()
58 : debugLevel_(10), backbufferFBO_(0), backbufferTarget_(GL_BACK), stereoMode_(false)
60 backbufferViewport_[0] = backbufferViewport_[1] = backbufferViewport_[2] = backbufferViewport_[3] = 0;
64 PostProcessing::~PostProcessing()
77 const int numProcs = postProcessorManager().
numActive(_viewerID);
79 if (!numProcs && _stereoEye < 0)
103 bool requiresFP =
false;
105 for (
int i = 0; i < numProcs && !requiresFP; ++i)
112 fmt.outputFormat_ = PostProcessorFormatDesc::PostProcessorFormat_DONTCARE;
113 pi->
plugin->getFormatDesc(&fmt);
115 if (!fmt.inputFormats_.empty())
117 size_t numInputs = fmt.inputFormats_.size();
119 for (
size_t k = 0; k < numInputs; ++k)
121 if (fmt.inputFormats_[k] == PostProcessorFormatDesc::PostProcessorFormat_FLOAT)
129 if (fmt.outputFormat_ == PostProcessorFormatDesc::PostProcessorFormat_FLOAT)
139 const int numEyes = _stereoEye < 0 ? 1 : 2;
141 GLuint texInternalFmt = requiresFP ? GL_RGBA32F : GL_RGBA;
147 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&backbufferFBO_);
148 glGetIntegerv(GL_DRAW_BUFFER, (GLint*)&backbufferTarget_);
149 glGetIntegerv(GL_VIEWPORT, backbufferViewport_);
154 for (
int i = 0; i < numEyes; ++i)
155 setupFBO(sceneFBO_ + i, _width, _height, texInternalFmt, _samples);
159 int numTempBuffers = std::min(numProcs - 1, 2);
162 numTempBuffers = std::min(numProcs, 2);
164 for (
int i = 0; i < numTempBuffers; ++i)
165 setupFBO(procFBO_ + i, _width, _height, texInternalFmt, 0);
168 for (
int i = 0; i < (_stereoEye >= 0 ? 2 : 0); ++i)
169 setupFBO(stereoFBO_ + i, _width, _height, texInternalFmt, 0);
174 int targetFboId = std::max(std::min(_stereoEye, 1), 0);
175 sceneFBO_[targetFboId].bind();
176 glDrawBuffer(GL_COLOR_ATTACHMENT0);
177 glViewport(0, 0, _width, _height);
180 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
183 stereoMode_ = _stereoEye >= 0;
187 glEnable(GL_MULTISAMPLE);
193 void PostProcessing::setupFBO(
ACG::FBO* _dst,
int _width,
int _height, GLuint _intfmt ,
int _samples )
196 GLuint filterMode = _samples ? GL_NEAREST : GL_LINEAR;
202 _dst->
attachTexture2D(GL_COLOR_ATTACHMENT0, _width, _height, _intfmt, GL_RGBA, GL_CLAMP, filterMode, filterMode);
220 _dst->
resize(_width, _height);
224 _dst->
attachTexture2D(GL_COLOR_ATTACHMENT0, _width, _height, _intfmt, GL_RGBA, GL_CLAMP, filterMode, filterMode);
232 if (sceneFBO_[0].getMultisamplingCount())
233 glDisable(GL_MULTISAMPLE);
239 std::vector<const PostProcessorInput*> postProcInputVec;
240 postProcInputVec.push_back(&postProcInput);
243 const int numProcs = postProcessorManager().
numActive(_viewerID);
246 int numChainExecs = stereoMode_ ? 2 : 1;
249 GLint saveDepthFunc = GL_LESS;
250 glGetIntegerv(GL_DEPTH_FUNC, &saveDepthFunc);
253 glColorMask(1,1,1,1);
258 for (
int chainId = 0; chainId < numChainExecs; ++chainId) {
262 postProcInput.width = sceneFBO_[chainId].width();
263 postProcInput.height = sceneFBO_[chainId].height();
265 postProcInput.depthRange_[0] = 0.0f;
266 postProcInput.depthRange_[1] = 1.0f;
268 postProcInput.view_ = _modelview;
269 postProcInput.proj_ = chainId ? _proj2 : _proj1;
272 if (sceneFBO_[chainId].getMultisamplingCount())
275 ACG::FBO* resolveTarget = numProcs ? &procFBO_[0] : &stereoFBO_[chainId];
277 if (numProcs || (stereoMode_ && !_hwOpenGLStereo))
278 resolveMultisampling(resolveTarget, &sceneFBO_[chainId]);
281 postProcInput.colorTex_ = resolveTarget->
getAttachment(GL_COLOR_ATTACHMENT0);
282 postProcInput.depthTex_ = resolveTarget->
getAttachment(GL_DEPTH_ATTACHMENT);
292 postProcInput.colorTex_ = sceneFBO_[chainId].getAttachment(GL_COLOR_ATTACHMENT0);
293 postProcInput.depthTex_ = sceneFBO_[chainId].getAttachment(GL_DEPTH_ATTACHMENT);
295 postProcInput.texfmt_ = sceneFBO_[chainId].getInternalFormat(GL_COLOR_ATTACHMENT0);
303 for (
int i = 0; i < numProcs; ++i) {
305 int postProcTarget = 1 - postProcSrc;
308 GLuint outputFBO = procFBO_[postProcTarget].getFboID();
309 GLuint outputDrawbuffer = GL_COLOR_ATTACHMENT0;
310 GLint outputViewport[4] = {0, 0, procFBO_[postProcTarget].width(), procFBO_[postProcTarget].height()};
312 const GLint* outputViewportPtr = outputViewport;
315 if (i + 1 == numProcs)
321 outputFBO = backbufferFBO_;
322 outputDrawbuffer = chainId ? GL_BACK_RIGHT : GL_BACK_LEFT;
324 outputViewportPtr = backbufferViewport_;
328 outputFBO = stereoFBO_[chainId].getFboID();
329 outputDrawbuffer = GL_COLOR_ATTACHMENT0;
331 outputViewport[0] = outputViewport[1] = 0;
332 outputViewport[2] = stereoFBO_[chainId].width();
333 outputViewport[3] = stereoFBO_[chainId].height();
338 outputFBO = backbufferFBO_;
339 outputDrawbuffer = backbufferTarget_;
340 outputViewportPtr = backbufferViewport_;
345 procFBO_[postProcTarget].width(), procFBO_[postProcTarget].height(), outputViewportPtr);
353 glColorMask(1,1,1,1);
355 glEnable(GL_CULL_FACE);
359 glDepthFunc(GL_LEQUAL);
366 GLint testFBO = 0, testDrawbuffer = 0;
369 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &testFBO);
370 glGetIntegerv(GL_DRAW_BUFFER, &testDrawbuffer);
371 glGetIntegerv(GL_VIEWPORT, testVp);
373 if (GLuint(testFBO) != postProcOutput.fbo_)
374 std::cerr <<
"Error: PostProcessor does not write to specified FBO: " << proc->
plugin->
postProcessorName().toStdString() << std::endl;
376 if (GLuint(testDrawbuffer) != postProcOutput.drawBuffer_)
377 std::cerr <<
"Error: PostProcessor does not write to specified draw-buffer: " << proc->
plugin->
postProcessorName().toStdString() << std::endl;
379 if (testVp[0] != postProcOutput.viewport_[0] || testVp[1] != postProcOutput.viewport_[1] ||
380 testVp[2] != postProcOutput.viewport_[2] || testVp[3] != postProcOutput.viewport_[3])
381 std::cerr <<
"Error: PostProcessor does not write to specified viewport: " << proc->
plugin->
postProcessorName().toStdString()
382 <<
" actual: (" << testVp[0] <<
" " << testVp[1] <<
" " << testVp[2] <<
" " << testVp[3] <<
") expected: (" 383 << postProcOutput.viewport_[0] <<
" " << postProcOutput.viewport_[1] <<
" " << postProcOutput.viewport_[2] <<
" " << postProcOutput.viewport_[3] <<
")" << std::endl;
388 postProcSrc = postProcTarget;
390 postProcInput.colorTex_ = procFBO_[postProcSrc].getAttachment(GL_COLOR_ATTACHMENT0);
397 glBindFramebuffer(GL_FRAMEBUFFER, backbufferFBO_);
398 glDrawBuffer(backbufferTarget_);
399 glViewport(backbufferViewport_[0], backbufferViewport_[1], backbufferViewport_[2], backbufferViewport_[3]);
402 glDepthFunc(saveDepthFunc);
407 const int resolveMethod = 0;
410 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curFbo);
412 if (resolveMethod == 0)
416 glBindFramebuffer(GL_READ_FRAMEBUFFER, _src->
getFboID());
417 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _dst->
getFboID());
422 std::cerr <<
"PostProcessing::resolveMultisampling - FBO size mismatch : src (" 423 << _src->
width() <<
" " << _src->
height() <<
") dst (" 424 << _dst->
width() <<
" " << _dst->
height() <<
")" << std::endl;
427 glBlitFramebuffer(0, 0, _src->
width(), _src->
height(),
429 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
436 glDrawBuffer(GL_COLOR_ATTACHMENT0);
437 GLuint multisampledColorTex = _src->
getAttachment(GL_COLOR_ATTACHMENT0);
438 GLuint multisampledDepthTex = _src->
getAttachment(GL_DEPTH_ATTACHMENT);
439 glDepthFunc(GL_ALWAYS);
440 ACG::MSTextureSampler::filterMSAATexture_Nearest(multisampledColorTex, multisampledDepthTex, _src->
getMultisamplingCount());
441 glDepthFunc(GL_LEQUAL);
446 glBindFramebuffer(GL_FRAMEBUFFER, curFbo);
457 const int numProcs = postProcessorManager().
numActive(_viewerID);
461 for (
int i = 0; i < 2; ++i)
465 ACG::FBO* eyeSrcFBO = &stereoFBO_[i];
467 if (!numProcs && !sceneFBO_[i].getMultisamplingCount())
468 eyeSrcFBO = &sceneFBO_[i];
470 inputs[i].colorTex_ = eyeSrcFBO->
getAttachment(GL_COLOR_ATTACHMENT0);
471 inputs[i].depthTex_ = eyeSrcFBO->
getAttachment(GL_DEPTH_ATTACHMENT);
472 inputs[i].width = eyeSrcFBO->
width();
473 inputs[i].height = eyeSrcFBO->
height();
479 std::vector<const PostProcessorInput*> anaglyphInputVec(2);
480 anaglyphInputVec[0] = inputs;
481 anaglyphInputVec[1] = inputs + 1;
485 inputs[0].width, inputs[0].height, backbufferViewport_);
490 std::cerr <<
"error: stereo anaglyph plugin missing!" << std::endl;
void attachTexture2DDepth(GLsizei _width, GLsizei _height, GLuint _internalFmt=GL_DEPTH_COMPONENT32, GLenum _format=GL_DEPTH_COMPONENT)
function to attach a depth-buffer texture to fbo (using GL_DEPTH_ATTACHMENT)
GLuint getFboID()
return opengl id
virtual void postProcess(ACG::GLState *_glState, const std::vector< const PostProcessorInput *> &_input, const PostProcessorOutput &_output)=0
post processor function
GLsizei getMultisamplingCount() const
get number of samples
GLsizei setMultisampling(GLsizei _samples, GLboolean _fixedsamplelocations=GL_TRUE)
void postProcess(int _viewerID, ACG::GLState *_glstate, const ACG::GLMatrixd &_modelview, const ACG::GLMatrixd &_proj1, const ACG::GLMatrixd &_proj2, bool _hwOpenGLStereo=false)
Perform all post processing.
PostProcessorInfo * getPostProcessor(QString _name)
get post processor with the given name
bool bind()
bind the fbo and sets it as rendertarget
PostProcessorInfo * active(int _id, int _chainIdx=0)
Get the current active post processor for viewer at chain index.
void resolveStereoAnyglyph(int _viewerID)
Resolve stereo buffers as anaglyph.
void resize(GLsizei _width, GLsizei _height, bool _forceResize=false)
resize function (if textures created by this class)
void attachTexture2D(GLenum _attachment, GLsizei _width, GLsizei _height, GLuint _internalFmt, GLenum _format, GLint _wrapMode=GL_CLAMP_TO_EDGE, GLint _minFilter=GL_NEAREST, GLint _magFilter=GL_NEAREST)
function to attach a texture to fbo
int setupScene(int _viewerID, int _width, int _height, int _samples=0, int _stereoEye=-1)
Bind fbo for scene rendering.
int numActive(int _id)
Get the number of active post processors for viewer.
GLsizei height() const
get height of fbo texture
PostProcessorInterface * plugin
Pointer to the loaded plugin (Already casted when loading it)
GLuint getInternalFormat(GLenum _attachment)
return internal texture format of attachment
GLsizei width() const
get width of fbo texture
ACG::Vec2i size() const
get width and height of fbo texture
GLuint getAttachment(GLenum _attachment)
return attached texture id
virtual QString postProcessorName()=0
announce name for the postProcessor function