Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
DepthPeeling.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision: 21016 $ *
45 * $LastChangedBy: schultz $ *
46 * $Date: 2015-07-16 16:48:42 +0200 (Do, 16 Jul 2015) $ *
47 * *
48 \*===========================================================================*/
49 
50 
51 #include <ACG/GL/acg_glew.hh>
52 
53 #include "DepthPeeling.hh"
54 
57 
58 
59 #include <ACG/GL/ShaderCache.hh>
60 #include <ACG/GL/GLError.hh>
61 #include <ACG/GL/ScreenQuad.hh>
62 
63 using namespace ACG;
64 
65 
66 // =================================================
67 // depth peeling shader modifier
68 
70 {
71 public:
72 
73 
75  {
76  _shader->addUniform("sampler2D g_DepthLayer");
77 
78  _shader->addOutput("float outDepth");
79  }
80 
81  void modifyFragmentBeginCode(QStringList* _code)
82  {
83  // compare current depth with previous layer
84  _code->push_back("float dp_prevDepth = texture(g_DepthLayer, sg_vScreenPos).x;");
85  _code->push_back("if (gl_FragCoord.z <= dp_prevDepth) discard;");
86  }
87 
88  void modifyFragmentEndCode(QStringList* _code)
89  {
90  _code->push_back("outFragment = vec4(sg_cColor.rgb * sg_cColor.a, sg_cColor.a);");
91  _code->push_back("outDepth = gl_FragCoord.z;");
92  }
93 
94  static PeelLayerModifier instance;
95 };
96 
97 
99 {
100 public:
101 
103  {
104  _shader->addOutput("float outDepth");
105  }
106 
107  void modifyFragmentEndCode(QStringList* _code)
108  {
109  _code->push_back("outFragment = vec4(sg_cColor.rgb * sg_cColor.a, 1.0 - sg_cColor.a);");
110  _code->push_back("outDepth = gl_FragCoord.z;");
111  }
112 
113  static PeelInitModifier instance;
114 };
115 
116 // for dual depth peeling only
118 {
119 public:
120 
122  {
123  _shader->addUniform("sampler2D g_DepthLayer");
124  _shader->addUniform("sampler2D g_FrontLayer");
125 
126  // MRT: color + depth output + last layer (eventually)
127  _shader->addOutput("vec4 outDepth");
128  _shader->addOutput("vec4 outBackColor");
129  }
130 
131  void modifyFragmentBeginCode(QStringList* _code)
132  {
133  _code->push_back("float fragDepth = gl_FragCoord.z;");
134 
135  _code->push_back("vec2 depthLayer = texture2D(g_DepthLayer, sg_vScreenPos).xy;");
136  _code->push_back("vec4 forwardTemp = texture2D(g_FrontLayer, sg_vScreenPos);");
137 
138  _code->push_back("outDepth = vec4(depthLayer, 0, 0);");
139  _code->push_back("outFragment = forwardTemp;");
140  _code->push_back("outBackColor = vec4(0,0,0,0);");
141 
142 
143  _code->push_back("float nearestDepth = -depthLayer.x;");
144  _code->push_back("float farthestDepth = depthLayer.y;");
145  _code->push_back("float alphaMultiplier = 1.0 - forwardTemp.w;");
146 
147 
148  _code->push_back("if (fragDepth < nearestDepth || fragDepth > farthestDepth) {");
149  _code->push_back("outDepth = vec4(-1,-1,-1,-1);");
150  _code->push_back("return;");
151  _code->push_back("}");
152 
153  _code->push_back("if (fragDepth > nearestDepth && fragDepth < farthestDepth) {");
154  _code->push_back("outDepth = vec4(-fragDepth, fragDepth, 0, 0);");
155  _code->push_back("return;");
156  _code->push_back("}");
157  }
158 
159 
160  void modifyFragmentEndCode(QStringList* _code)
161  {
162  _code->push_back("outDepth = vec4(-1,-1,-1,-1);");
163  _code->push_back("outFragment = forwardTemp;");
164 
165  _code->push_back("if (fragDepth == nearestDepth) {");
166  _code->push_back("outFragment.xyz += sg_cColor.rgb * sg_cColor.a * alphaMultiplier;");
167  _code->push_back("outFragment.w = 1.0 - alphaMultiplier * (1.0 - sg_cColor.a);");
168 
169 // _code->push_back("outFragment = vec4(alphaMultiplier,alphaMultiplier,alphaMultiplier,1);");
170 
171  _code->push_back("} else {");
172  _code->push_back("outBackColor += sg_cColor;");
173  _code->push_back("}");
174  }
175 
176  static PeelDualLayerModifier instance;
177 };
178 
180 {
181 public:
182  void modifyFragmentEndCode(QStringList* _code)
183  {
184  _code->push_back("outFragment = vec4(-gl_FragCoord.z, gl_FragCoord.z, 0, 0);");
185  }
186 
187  static PeelDualInitModifier instance;
188 };
189 
190 
191 PeelInitModifier PeelInitModifier::instance;
192 PeelLayerModifier PeelLayerModifier::instance;
193 PeelDualLayerModifier PeelDualLayerModifier::instance;
194 PeelDualInitModifier PeelDualInitModifier::instance;
195 
196 // internal shader-attribute flags
197 
198 #define RENDERFLAG_ALLOW_PEELING 1
199 
200 
201 // =================================================
202 
203 DepthPeeling::DepthPeeling()
204  : peelMode_(1), copyFrontDepth_(1), maxPeelCount_(20), peelBlend_(0), peelFinal_(0), peelQueryID_(0),
205 peelBlendDual_(0), peelFinalDual_(0)
206 {
207 }
208 
209 
210 DepthPeeling::~DepthPeeling()
211 {
212 }
213 
214 
215 
216 QString DepthPeeling::checkOpenGL()
217 {
218  if (!ACG::openGLVersion(3, 2))
219  return QString("Insufficient OpenGL Version! OpenGL 3.2 or higher required");
220 
221  QString missing("");
222 
223  if (!ACG::checkExtensionSupported("GL_ARB_vertex_buffer_object"))
224  missing += "GL_ARB_vertex_buffer_object extension missing\n";
225 
226 #ifndef __APPLE__
227  if (!ACG::checkExtensionSupported("GL_ARB_vertex_program"))
228  missing += "GL_ARB_vertex_program extension missing\n";
229 #endif
230 
231  if (!ACG::checkExtensionSupported("GL_ARB_occlusion_query"))
232  missing += "GL_ARB_occlusion_query extension missing\n";
233 
234  return missing;
235 }
236 
237 
238 void DepthPeeling::initializePlugin()
239 {
240  ACG::ShaderProgGenerator::setShaderDir(OpenFlipper::Options::shaderDirStr());
241 }
242 
243 void DepthPeeling::slotModeChanged( QAction * _action)
244 {
245  // Prepare Picking Debugger Flag
246  if ( _action->text() == "Front to Back") {
247  peelMode_ = 0;
248  } else if ( _action->text() == "Dual") {
249  peelMode_ = 1;
250  } else {
251  std::cerr << "Error : optionHandling unable to find peeling mode!!! " << _action->text().toStdString() << std::endl;
252  peelMode_ = 1;
253  }
254 }
255 
256 void DepthPeeling::render(ACG::GLState* _glState, Viewer::ViewerProperties& _properties)
257 {
258  // debugging utilities
259 // if (!dbgProg_)
260 // dbgProg_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/dbg_shader.glsl");
261 
262 
263  // collect renderobjects
265 
266 
267  if (peelMode_ == 0)
268  renderFrontPeeling(_glState, _properties);
269  else
270  renderDualPeeling(_glState, _properties);
271 
272  // restore common opengl state
273  // log window remains hidden otherwise
275 }
276 
277 
278 
279 
280 
282  Viewer::ViewerProperties& _properties)
283 {
284  const int numRenderObjects = getNumRenderObjects();
285 
286  // begin rendering
287  // find last transparent object
288  int lastPeeledObject = -1;
289 
290  for (int i = numRenderObjects - 1; i > lastPeeledObject; --i)
291  {
292  if ((sortedObjects_[i]->internalFlags_ & RENDERFLAG_ALLOW_PEELING) && sortedObjects_[i]->alpha < 0.99f)
293  lastPeeledObject = i;
294  }
295 
296  if (lastPeeledObject == -1)
297  {
298  // no transparent objects
299  for (int i = 0; i < numRenderObjects; ++i)
301  }
302  else
303  {
304  // depth peeling code
305 
306  // make sure shaders and occlusion query are initialized
308 
309  // resize fbo as necessary
310  ViewerResources* viewRes = &viewerRes_[_properties.viewerId()];
311  viewRes->resize(false, (unsigned int)_glState->viewport_width(), (unsigned int)_glState->viewport_height());
312 
313 
314  // init MRT slots:
315  // RT0 - color blend texture
316  // RT1 - depth buffer copy
317  const GLenum depthTarget = GL_COLOR_ATTACHMENT0;
318  const GLenum colorTarget = GL_COLOR_ATTACHMENT1;
319  const GLenum colorBlendTarget = GL_COLOR_ATTACHMENT4;
320  GLenum peelLayerTargets[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
321 
322  const float clearDepth = 1.0f;
323 
324  // begin peeling
325  // draw first layer
326  // target depth buffer: depth0, front0
327  glViewport(0, 0, viewRes->width_, viewRes->height_);
328  glBindFramebuffer(GL_FRAMEBUFFER, viewRes->singleFbo_->getFboID());
329 
330  // allow color+depth write access
331  glDepthMask(1);
332  glColorMask(1,1,1,1);
333 
334  // clear color blend target
335  glDrawBuffer(colorBlendTarget);
336  glClearColor(_glState->clear_color()[0], _glState->clear_color()[1], _glState->clear_color()[2], 0);
337  glClear(GL_COLOR_BUFFER_BIT);
338 
339  // clear colors (front and back colors per pass)
340  glDrawBuffer(colorTarget);
341  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
342  glClear(GL_COLOR_BUFFER_BIT);
343 
344  // clear depths
345  glDrawBuffer(depthTarget);
346  glClearColor(clearDepth, 0.0f, 0.0f, 0.0f);
347  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
348 
349 
350  // 1. Pass: initialize depth values
351  // the init shader also writes the first front layer colors in accumulation buffer
352  peelLayerTargets[0] = colorBlendTarget;
353  peelLayerTargets[1] = depthTarget;
354  glDrawBuffers(2, peelLayerTargets); // write to MRT slots (color, depth)
355 
356  glDisable(GL_BLEND);
357  glDisable(GL_ALPHA_TEST);
358 
359  glEnable(GL_DEPTH_TEST);
360  glDepthFunc(GL_LESS);
361  glDisable(GL_CULL_FACE);
362 
363  for (int i = 0; i < numRenderObjects; ++i)
364  {
365 // if ((sortedObjects_[i]->internalFlags_ & RENDERFLAG_ALLOW_PEELING) && sortedObjects_[i]->alpha < 0.99f)
366  {
367  GLSL::Program* initProg = ShaderCache::getInstance()->getProgram(&sortedObjects_[i]->shaderDesc, PeelInitModifier::instance);
368 
369  if (initProg->getFragDataLocation("outFragment") != 0 || initProg->getFragDataLocation("outDepth") != 1)
370  {
371  initProg->bindFragDataLocation(0, "outFragment"); // color -> slot0
372  initProg->bindFragDataLocation(1, "outDepth"); // depth -> slot1
373  initProg->link();
374  }
375 
376  renderObject(sortedObjects_[i], initProg, true);
377  }
378  }
379 
380  // copy depth values to input depth buffer if requested
381  if (copyFrontDepth_)
382  copyDepthToBackBuffer(viewRes->singleDepthTex_[0], 1.0f);
383 
384  // peel layers, we start at index 1 instead of 0
385  // since the front layer is already initialized in
386  // depth buffer 0 and we want to extract the second one now
387 
388  for (int pass = 1; pass < maxPeelCount_; ++pass)
389  {
390  const int currID = pass & 1;
391  const int prevID = 1 - currID;
392  const int bufID = currID * 2;
393 
394  // peeling MRT slots:
395  // RT0 - color
396  // RT1 - depth buffer copy
397  const GLenum targetBuffer[2] = {colorTarget + bufID, depthTarget + bufID};
398 
399  // ---------------------------------------------------------------
400  // 1st peel next layer
401 
402  // clear color texture
403  glDrawBuffer(targetBuffer[0]);
404  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
405  glClear(GL_COLOR_BUFFER_BIT);
406  // clear depth texture
407  glDrawBuffer(targetBuffer[1]);
408  glClearColor(clearDepth, 0.0f, 0.0f, 0.0f);
409  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
410 
411 
412  glDrawBuffers(2, targetBuffer);
413 
414 
415  glDisable(GL_BLEND);
416  glEnable(GL_DEPTH_TEST);
417 
418  // count # passed fragments
419  glBeginQuery(GL_SAMPLES_PASSED, peelQueryID_);
420 
421 
422  // bind previous depth layer to texture unit 4
423  glActiveTexture(GL_TEXTURE4);
424  glBindTexture(GL_TEXTURE_2D, viewRes->singleDepthTex_[prevID]);
425 
426  // render scene
427  for (int k = 0; k < numRenderObjects; ++k)
428  {
429  if ((sortedObjects_[k]->internalFlags_ & RENDERFLAG_ALLOW_PEELING) && sortedObjects_[k]->alpha < 0.99f)
430  {
431  GLSL::Program* peelProg = ShaderCache::getInstance()->getProgram(&sortedObjects_[k]->shaderDesc, PeelLayerModifier::instance);
432 
433  if (peelProg->getFragDataLocation("outFragment") != 0 || peelProg->getFragDataLocation("outDepth") != 1)
434  {
435  peelProg->bindFragDataLocation(0, "outFragment");
436  peelProg->bindFragDataLocation(1, "outDepth");
437  peelProg->link();
438  }
439 
440  peelProg->use();
441  peelProg->setUniform("g_DepthLayer", 4);
442 
443  renderObject(sortedObjects_[k], peelProg, true);
444  }
445  }
446 
447  glEndQuery(GL_SAMPLES_PASSED);
448 
449 
450 
451  // ---------------------------------------------------------------
452  // 2nd underblend layer with current scene
453  // (fullscreen pass)
454  glDrawBuffer(colorBlendTarget);
455 
456  glDepthMask(1);
457  glColorMask(1,1,1,1);
458 
459  glDisable(GL_DEPTH_TEST);
460  glEnable(GL_BLEND);
461 
462  glBlendEquation(GL_FUNC_ADD);
463  ACG::GLState::blendFuncSeparate(GL_DST_ALPHA, GL_ONE,
464  GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
465 
466 
467  peelBlend_->use();
468  peelBlend_->setUniform("BlendTex", 0);
469 
470  glActiveTexture(GL_TEXTURE0);
471  glBindTexture(GL_TEXTURE_2D, viewRes->singleFrontTex_[currID]);
472 
474 
475 
476  glDisable(GL_BLEND);
477 
478 
479 
480  GLuint passedSamples;
481  glGetQueryObjectuiv(peelQueryID_, GL_QUERY_RESULT, &passedSamples);
482  if (passedSamples == 0)
483  break;
484  }
485 
486 
487  // copy to back buffer
488  restoreInputFbo();
489 
490  glDepthMask(1);
491  glColorMask(1,1,1,1);
492 
493  glDisable(GL_DEPTH_TEST);
494 
495  peelFinal_->use();
496 
497 
498  ACG::Vec3f bkgColor;
499  bkgColor[0] = _properties.backgroundColor()[0];
500  bkgColor[1] = _properties.backgroundColor()[1];
501  bkgColor[2] = _properties.backgroundColor()[2];
502 
503  peelFinal_->setUniform("BkgColor", bkgColor);
504 
505  peelFinal_->setUniform("SceneTex", 0);
506 
507  glActiveTexture(GL_TEXTURE0);
508  glBindTexture(GL_TEXTURE_2D, viewRes->singleBlendTex_);
509 
511 
513 
514 
515 
516 
517  // draw rest of scene
518  glEnable(GL_DEPTH_TEST);
519 
520 
521 // // draw rest of opaque objects
522 // for (int i = lastPeeledObject + 1; i < numRenderObjects; ++i)
523 // renderObject(sortedObjects_[i]);
524 
525  }
526 }
527 
528 
530 {
531  const int numRenderObjects = getNumRenderObjects();
532 
533  // begin rendering
534  // find last transparent object
535  int lastPeeledObject = -1;
536 
537  for (int i = numRenderObjects - 1; i > lastPeeledObject; --i)
538  {
539  if ((sortedObjects_[i]->internalFlags_ & RENDERFLAG_ALLOW_PEELING) && sortedObjects_[i]->alpha < 0.99f)
540  lastPeeledObject = i;
541  }
542 
543  if (0) //lastPeeledObject == -1)
544  {
545  // no transparent objects
546  for (int i = 0; i < numRenderObjects; ++i)
548  }
549  else
550  {
551  // depth peeling code
552 
553  // make sure shaders and occlusion query are initialized
555 
556  // resize fbo as necessary
557  ViewerResources* viewRes = &viewerRes_[_properties.viewerId()];
558  viewRes->resize(true, (unsigned int)_glState->viewport_width(), (unsigned int)_glState->viewport_height());
559 
560 
561  // enable color/depth write access
562  glDepthMask(1);
563  glColorMask(1,1,1,1);
564 
565 
566  // clear render targets
567 // viewRes->dualFboACG_->bind();
568  glViewport(0, 0, _glState->viewport_width(), _glState->viewport_height());
569  glBindFramebuffer(GL_FRAMEBUFFER, viewRes->dualFbo_->getFboID());
570 
571  const GLenum depthTarget = GL_COLOR_ATTACHMENT0; // stores (-minDepth, maxDepth)
572  const GLenum colorTargets[] = {GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
573  const GLenum colorBlendTarget = GL_COLOR_ATTACHMENT6;
574 
575  // clear colors (front and back colors per pass)
576  glDrawBuffers(2, colorTargets);
577  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
578  glClear(GL_COLOR_BUFFER_BIT);
579 
580  // clear color blend target
581  glDrawBuffer(colorBlendTarget);
582  glClearColor(_glState->clear_color()[0], _glState->clear_color()[1], _glState->clear_color()[2], 0);
583  glClear(GL_COLOR_BUFFER_BIT);
584 
585  // clear depths
586  glDrawBuffer(depthTarget);
587  glClearColor(-1.0f, -1.0f, 0.0f, 0.0f);
588  glClear(GL_COLOR_BUFFER_BIT);
589 
590 
591  // 1. Pass: initialize depth values
592  // the init shader writes min/max depth values (-z, +z)
593  glEnable(GL_BLEND);
594  glBlendEquation(GL_MAX_EXT); // get min/max depth
595 
596  glDisable(GL_ALPHA_TEST);
597 
598  glEnable(GL_DEPTH_TEST);
599  glDepthFunc(GL_LESS);
600  glDisable(GL_CULL_FACE);
601 
602  for (int i = 0; i < numRenderObjects; ++i)
603  {
604  GLSL::Program* initProg = ShaderCache::getInstance()->getProgram(&sortedObjects_[i]->shaderDesc, PeelDualInitModifier::instance);
605 
606  renderObject(sortedObjects_[i], initProg, true);
607  }
608 
609 
610  // copy depth values of first front layer to input depth buffer if requested
611  if (copyFrontDepth_)
612  {
613  glDisable(GL_BLEND);
614  copyDepthToBackBuffer(viewRes->dualDepthTex_[0], -1.0f);
615  // dual peeling requires blending
616  glEnable(GL_BLEND);
617  }
618 
619  // 2. peeling passes + color accumulation
620 
621  int currID = 0; // ping-pong render targets
622 
623 //if (0){
624 
625  for (int pass = 1; 1 && pass < maxPeelCount_; ++pass)
626  {
627  currID = pass & 1;
628  const int prevID = 1 - currID;
629  const int bufID = currID * 3;
630 
631  GLenum targetBuffer[3];
632  targetBuffer[0] = GL_COLOR_ATTACHMENT0 + bufID;
633  targetBuffer[1] = GL_COLOR_ATTACHMENT1 + bufID;
634  targetBuffer[2] = GL_COLOR_ATTACHMENT2 + bufID;
635 // GLenum sourceBuffer[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
636 
637  // clear target colors
638  glDrawBuffers(2, targetBuffer + 1);
639  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
640  glClear(GL_COLOR_BUFFER_BIT);
641 
642  // clear target depth
643  glDrawBuffer(targetBuffer[0]);
644  glClearColor(-1.0f, -1.0f, 0.0f, 0.0f);
645  glClear(GL_COLOR_BUFFER_BIT);
646 
647 
648 
649  // Peel pass
650 
651  // set target
652  glBlendEquation(GL_MAX_EXT);
653  glDrawBuffers(3, targetBuffer); // shader writes to (depth_tex, front_color_tex, back_color_tex)
654 
655  // set texture source (provide previous layer)
656  // slot 4 - depth
657  // slot 5 - front color
658 
659  glActiveTexture(GL_TEXTURE5);
660  glBindTexture(GL_TEXTURE_2D, viewRes->dualFrontTex_[prevID]);
661 
662  glActiveTexture(GL_TEXTURE4);
663  glBindTexture(GL_TEXTURE_2D, viewRes->dualDepthTex_[prevID]);
664 
665  // restore active tex marker to default slot
666  glActiveTexture(GL_TEXTURE0);
667 
668  // peel scene
669  for (int i = 0; i < numRenderObjects; ++i)
670  {
671  GLSL::Program* peelProg = ShaderCache::getInstance()->getProgram(&sortedObjects_[i]->shaderDesc, PeelDualLayerModifier::instance);
672 
673  peelProg->use();
674  peelProg->setUniform("g_DepthLayer", 4);
675  peelProg->setUniform("g_FrontLayer", 5);
676 
677  // setup MRT
678  // outFragment -> front
679  // outDepth -> depth
680  // outBackColor -> back
681 
682  int locOutFrag = peelProg->getFragDataLocation("outFragment");
683  int locOutDepth = peelProg->getFragDataLocation("outDepth");
684  int locOutBackColor = peelProg->getFragDataLocation("outBackColor");
685 
686  if (locOutFrag != 1 ||
687  locOutDepth != 0 ||
688  locOutBackColor != 2)
689  {
690  // linking is slow; only link if necessary
691  peelProg->bindFragDataLocation(1, "outFragment");
692  peelProg->bindFragDataLocation(0, "outDepth");
693  peelProg->bindFragDataLocation(2, "outBackColor");
694 
695  peelProg->link();
696  }
697 
698 
699 
700  renderObject(sortedObjects_[i], peelProg, true);
701  }
702 
703 
704 
705 
706  // ----------------------
707  // debugging
708 /*
709  if (pass == 1)
710  {
711  dbgDrawTex(viewRes->dualFrontTex_[currID]);
712  return;
713  }
714 */
715  //
716 
717 
718 
719 
720  // blend back color into accumulation buffer
721  glDrawBuffer(colorBlendTarget);
722 
723  glBlendEquationEXT(GL_FUNC_ADD);
724  ACG::GLState::blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
725 
726  // bind back color texture to slot 0
727  glActiveTexture(GL_TEXTURE0);
728  glBindTexture(GL_TEXTURE_2D, viewRes->dualBackTex_[currID]);
729 
730 
731  glBeginQuery(GL_SAMPLES_PASSED_ARB, peelQueryID_);
732 
733  peelBlendDual_->use();
734  peelBlendDual_->setUniform("BlendTex", 0);
735 
737 
738  glEndQuery(GL_SAMPLES_PASSED_ARB);
739 
740 
741 
742  // termination check
743  GLuint passedSamples;
744  glGetQueryObjectuiv(peelQueryID_, GL_QUERY_RESULT, &passedSamples);
745  if (passedSamples == 0)
746  break;
747  }
748 
749 //}
750 
751  // Final pass: combine accumulated front and back colors
752  restoreInputFbo();
753 
754  glDepthMask(1);
755  glColorMask(1,1,1,1);
756 
757  glDisable(GL_DEPTH_TEST);
758  glDisable(GL_BLEND);
759 
760 
761  peelFinalDual_->use();
762 
763 
764  ACG::Vec3f bkgColor;
765  bkgColor[0] = _properties.backgroundColor()[0];
766  bkgColor[1] = _properties.backgroundColor()[1];
767  bkgColor[2] = _properties.backgroundColor()[2];
768 
769  peelFinalDual_->setUniform("BkgColor", bkgColor);
770 
771  // slot 0 - front colors
772  // slot 1 - back colors
773 
774  peelFinalDual_->setUniform("FrontSceneTex", 0);
775  peelFinalDual_->setUniform("BackSceneTex", 1);
776 
777  glActiveTexture(GL_TEXTURE1);
778  glBindTexture(GL_TEXTURE_2D, viewRes->dualBlendTex_);
779 
780  glActiveTexture(GL_TEXTURE0);
781  glBindTexture(GL_TEXTURE_2D, viewRes->dualFrontTex_[currID]);
782 
783 // drawProjQuad(peelFinalDual_);
784  ACG::ScreenQuad::draw(peelFinalDual_);
785 
786 
787  peelFinalDual_->disable();
788 
789 
790 
791 
792 
793  // ------------------------------------------
794  // debugging
795 
796 // dbgDrawTex(viewRes->dualDepthTex_[0]);
797 
798 
799  // ------------------------------------------
800 
801 
802 
803 
804 
805 
806 
807 
809 
810 
811 // // draw rest of scene
812 // glEnable(GL_DEPTH_TEST);
813 //
814 //
815 // // draw rest of opaque objects
816 // for (int i = lastPeeledObject + 1; i < numRenderObjects; ++i)
817 // renderObject(sortedObjects_[i]);
818 
819  }
820 }
821 
823 {
824  // do some more checks for error detection
825  if (!_renderObject->vertexDecl)
826  std::cout << "error: missing vertex declaration" << std::endl;
827  else
828  {
829  renderObjects_.push_back(*_renderObject);
830 
831 
832  RenderObject* p = &renderObjects_.back();
833 
834  if (!p->shaderDesc.numLights)
835  p->shaderDesc.numLights = numLights_;
836 
837  else if (p->shaderDesc.numLights < 0 || p->shaderDesc.numLights >= SG_MAX_SHADER_LIGHTS)
838  p->shaderDesc.numLights = 0;
839 
840  p->internalFlags_ = 0;
841 
842  // allow potential depth peeling only for compatible
843  // render states
844 
845  if (p->alpha < 1.0f &&
846  p->depthTest &&
847  p->depthWrite && (p->depthFunc == GL_LESS ||
848  p->depthFunc == GL_LEQUAL))
849  p->internalFlags_ = RENDERFLAG_ALLOW_PEELING;
850 
851 
852  // precompile shader
853  ShaderCache::getInstance()->getProgram(&p->shaderDesc);
854 
855  }
856 }
857 
858 
859 
860 
861 DepthPeeling::ViewerResources::ViewerResources()
862 : width_(0), height_(0), singleBlendTex_(0), singleFbo_(0), dualBlendTex_(0), dualFbo_(0)
863 {
864  memset(singleDepthTex_, 0, sizeof(singleDepthTex_));
865  memset(singleFrontTex_, 0, sizeof(singleFrontTex_));
866 
867  memset(dualDepthTex_, 0, sizeof(dualDepthTex_));
868  memset(dualFrontTex_, 0, sizeof(dualFrontTex_));
869  memset(dualBackTex_, 0, sizeof(dualBackTex_));
870 }
871 
872 
873 DepthPeeling::ViewerResources::~ViewerResources()
874 {
875  delete singleFbo_;
876  delete dualFbo_;
877 }
878 
879 
880 void DepthPeeling::ViewerResources::resize(bool _dualPeeling, unsigned int _width, unsigned int _height)
881 {
882  if (!_width || !_height)
883  return;
884 
885  width_ = _width;
886  height_ = _height;
887 
888  if (!_dualPeeling)
889  {
890  if (!singleFbo_)
891  {
892  singleFbo_ = new ACG::FBO();
893 
894  singleFbo_->init();
895 
896  // texture formats:
897  // depth textures: store layer depth as float
898  // front color textures: store (r,g,b,a) colors as R8G8B8A8
899  // color blending and accumulation texture: (r,g,b,a) color as R8G8B8A8
900 
901  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT0, width_, height_, GL_R32F, GL_RGB, GL_CLAMP, GL_NEAREST, GL_NEAREST);
902  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT1, width_, height_, GL_RGBA, GL_RGBA, GL_CLAMP, GL_NEAREST, GL_NEAREST);
903 
904  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT2, width_, height_, GL_R32F, GL_RGB, GL_CLAMP, GL_NEAREST, GL_NEAREST);
905  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT3, width_, height_, GL_RGBA, GL_RGBA, GL_CLAMP, GL_NEAREST, GL_NEAREST);
906 
907  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT4, width_, height_, GL_RGBA, GL_RGBA, GL_CLAMP, GL_NEAREST, GL_NEAREST);
908 
909  singleFbo_->attachTexture2DDepth(width_, height_);
910 
911  singleDepthTex_[0] = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT0);
912  singleDepthTex_[1] = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT2);
913 
914  singleFrontTex_[0] = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT1);
915  singleFrontTex_[1] = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT3);
916 
917  singleBlendTex_ = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT4);
918 
919 
920  singleFbo_->checkFramebufferStatus();
921 
923  }
924  else
925  singleFbo_->resize(_width, _height);
926 
927  }
928  else
929  {
930  // dual peeling render targets
931 
932  // fbo
933  if (!dualFbo_)
934  {
935  dualFbo_ = new ACG::FBO();
936 
937  dualFbo_->init();
938 
939  // texture formats:
940  // depth textures: store (min,max) depth as float2
941  // front+back color textures: store (r,g,b,a) colors as R8G8B8A8
942  // color blending and accumulation texture: (r,g,b) color as R8G8B8X8
943 
944  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT0, width_, height_, GL_RG32F, GL_RGB, GL_CLAMP, GL_NEAREST, GL_NEAREST);
945  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT1, width_, height_, GL_RGBA, GL_RGBA, GL_CLAMP, GL_NEAREST, GL_NEAREST);
946  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT2, width_, height_, GL_RGBA, GL_RGBA, GL_CLAMP, GL_NEAREST, GL_NEAREST);
947 
948  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT3, width_, height_, GL_RG32F, GL_RGB, GL_CLAMP, GL_NEAREST, GL_NEAREST);
949  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT4, width_, height_, GL_RGBA, GL_RGBA, GL_CLAMP, GL_NEAREST, GL_NEAREST);
950  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT5, width_, height_, GL_RGBA, GL_RGBA, GL_CLAMP, GL_NEAREST, GL_NEAREST);
951 
952  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT6, width_, height_, GL_RGB, GL_RGB, GL_CLAMP, GL_NEAREST, GL_NEAREST);
953 
954  dualDepthTex_[0] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT0);
955  dualDepthTex_[1] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT3);
956 
957  dualFrontTex_[0] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT1);
958  dualFrontTex_[1] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT4);
959 
960  dualBackTex_[0] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT2);
961  dualBackTex_[1] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT5);
962 
963  dualBlendTex_ = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT6);
964 
965 
966  dualFbo_->checkFramebufferStatus();
967 
969  }
970  else
971  dualFbo_->resize(_width, _height);
972 
973  }
974 
975 
976  glBindFramebuffer(GL_FRAMEBUFFER, 0);
977 
979 }
980 
982 {
983  // check if already initialized
985  return;
986 
987  // register shader modifiers
988  ShaderProgGenerator::registerModifier(&PeelInitModifier::instance);
989  ShaderProgGenerator::registerModifier(&PeelLayerModifier::instance);
990 
991  // load intermediate blending and final shader
992  if (!peelBlend_)
993  peelBlend_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/blend.glsl");
994 
995  if (!peelFinal_)
996  peelFinal_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/final.glsl");
997 
998  // occ query id
999  if (!peelQueryID_)
1000  glGenQueries(1, &peelQueryID_);
1001 
1003 }
1004 
1006 {
1007  // check if already initialized
1008  if (peelBlendDual_ && peelFinalDual_ && peelQueryID_)
1009  return;
1010 
1011  // register shader modifiers
1012  ShaderProgGenerator::registerModifier(&PeelDualInitModifier::instance);
1013  ShaderProgGenerator::registerModifier(&PeelDualLayerModifier::instance);
1014 
1015  // load intermediate blending and final shader
1016  if (!peelBlendDual_)
1017  peelBlendDual_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/blend_dual.glsl");
1018 
1019  if (!peelFinalDual_)
1020  peelFinalDual_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/final_dual.glsl");
1021 
1022  // occ query id
1023  if (!peelQueryID_)
1024  glGenQueries(1, &peelQueryID_);
1025 
1027 }
1028 
1029 QString DepthPeeling::renderObjectsInfo( bool _outputShaderInfo )
1030 {
1031  QString infoString;
1032 
1033  ACG::ShaderModifier* availableMods[4] =
1034  {
1035  &PeelInitModifier::instance, &PeelLayerModifier::instance,
1036  &PeelDualInitModifier::instance, &PeelDualLayerModifier::instance
1037  };
1038 
1039 
1040  // write modified shaders for init and peel passes
1041 
1042  infoString += "PeelInit:\n\n\n";
1043 
1044  std::vector<ACG::ShaderModifier*> mods;
1045  mods.push_back(availableMods[peelMode_*2]);
1046 
1047  infoString += dumpCurrentRenderObjectsToString(&sortedObjects_[0],_outputShaderInfo, &mods);
1048 
1049 
1050  infoString += "\n\n-----------------------------------------------\n\n\n\n";
1051  infoString += "PeelLayer:\n\n\n";
1052 
1053  mods[0] = availableMods[peelMode_*2 + 1];
1054 
1055  infoString += dumpCurrentRenderObjectsToString(&sortedObjects_[0],_outputShaderInfo, &mods);
1056 
1057  return infoString;
1058 }
1059 
1060 
1061 //
1062 // void DepthPeeling::dbgDrawTex( GLuint _texID )
1063 // {
1064 // glBindFramebuffer(GL_FRAMEBUFFER, 0);
1065 // glDrawBuffer(GL_BACK);
1066 // glClearColor(0,0,0,0);
1067 // glClear(GL_COLOR_BUFFER_BIT);
1068 //
1069 //
1070 // glDepthMask(1);
1071 // glColorMask(1,1,1,1);
1072 //
1073 // glDisable(GL_DEPTH_TEST);
1074 // glDisable(GL_BLEND);
1075 //
1076 // dbgProg_->use();
1077 //
1078 // dbgProg_->setUniform("Tex", 0);
1079 //
1080 // glActiveTexture(GL_TEXTURE0);
1081 // glBindTexture(GL_TEXTURE_2D, _texID);
1082 //
1083 // drawProjQuad(dbgProg_);
1084 //
1085 // dbgProg_->disable();
1086 // }
1087 //
1088 
1089 
1090 
1091 #if QT_VERSION < 0x050000
1092  Q_EXPORT_PLUGIN2( depthpeelingshaderrenderer , DepthPeeling );
1093 #endif
1094 
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
Definition: DepthPeeling.cc:81
ShaderGenDesc shaderDesc
Drawmode and other shader params.
GLSL::Program * peelBlend_
blends one depth-layer into the current scene target
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
void initDualDepthPeeling()
Allocate framebuffers and load shaders for dual-depth-peeling.
void addUniform(QString _uniform, QString _comment="")
Add one GLSL uniform specifier.
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
int maxPeelCount_
max peel count
GLuint peelQueryID_
occlusion query determining end of peeling (last layer)
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:730
virtual void renderObject(ACG::RenderObject *_obj, GLSL::Program *_prog=0, bool _constRenderStates=false, const std::vector< unsigned int > *_shaderModifiers=0)
Render one renderobject.
Definition: IRenderer.cc:986
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:924
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
static void blendFuncSeparate(GLenum _srcRGB, GLenum _dstRGB, GLenum _srcAlpha, GLenum _dstAlpha)
replaces glBlendFuncSeparate, supports locking
Definition: GLState.cc:1592
Interface class between scenegraph and renderer.
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:698
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
Definition: DepthPeeling.cc:74
std::vector< ACG::RenderObject * > sortedObjects_
sorted list of renderobjects without overlay objects (sorted in rendering order)
Definition: IRenderer.hh:463
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:147
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1082
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
Definition: DepthPeeling.cc:88
Definition: FBO.hh:83
unsigned int internalFlags_
may be used internally by the renderer
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
void addOutput(const QString &_output)
Add one GLSL output specifier.
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:73
virtual QString dumpCurrentRenderObjectsToString(ACG::RenderObject **_list=0, bool _outputShaders=false, std::vector< ACG::ShaderModifier * > *_modifiers=0)
Outputs the current render objects to the string.
Definition: IRenderer.cc:1135
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
Collection of framebuffers for each viewport.
int viewport_width() const
get viewport width
Definition: GLState.hh:825
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:314
GLuint getFboID()
return opengl id
Definition: FBO.cc:597
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
QString renderObjectsInfo(bool _outputShaderInfo)
Return a qstring of the current render objects.
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
int peelMode_
mode: 0 -> front to back peeling, 1 -> dual peeling
int numLights_
Number of Lights.
Definition: IRenderer.hh:449
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:332
void glCheckErrors()
Definition: GLError.hh:105
std::vector< ACG::RenderObject > renderObjects_
array of renderobjects, filled by addRenderObject()
Definition: IRenderer.hh:459
virtual void copyDepthToBackBuffer(GLuint _depthTex, float _scale=1.0f)
Copy texture to depth buffer.
Definition: IRenderer.cc:1200
void renderDualPeeling(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
peel the scene with dual depth peeling, two layers per pass
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
GLSL::Program * peelFinal_
final copy into back-buffer
GLSL program class.
Definition: GLSLShader.hh:217
static void setShaderDir(QString _dir)
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
void renderFrontPeeling(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
peel the scene from front to back, one layer per pass
virtual void finishRenderingPipeline(bool _drawOverlay=true)
Draw overlay objects and reset OpenGL state.
Definition: IRenderer.cc:589
virtual void restoreInputFbo()
Restore the previously saved input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:700
void initDepthPeeling()
Allocate framebuffers and load shaders for depth-peeling.
void addRenderObject(ACG::RenderObject *_renderObject)
overide addRenderObject function to include OIT check
virtual void prepareRenderingPipeline(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode *_scenegraphRoot)
Prepares renderer and OpenGL for any draw-related calls including.
Definition: IRenderer.cc:486
GLSL::Program * peelBlendDual_
dual depth peeling shaders
void disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:361
unsigned int height_
viewer window height
int viewport_height() const
get viewport height
Definition: GLState.hh:827
std::map< int, ViewerResources > viewerRes_
ACG::Vec4f backgroundColor()
Get current background color.
unsigned int width_
viewer window width
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects) ...
Definition: IRenderer.cc:1045