Developer Documentation
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 #include <ACG/GL/acg_glew.hh>
45 
46 #include "DepthPeeling.hh"
47 
50 
51 
52 #include <ACG/GL/ShaderCache.hh>
53 #include <ACG/GL/GLError.hh>
54 #include <ACG/GL/ScreenQuad.hh>
55 
56 using namespace ACG;
57 
58 
59 // =================================================
60 // depth peeling shader modifier
61 
63 {
64 public:
65 
66 
68  {
69  _shader->addUniform("sampler2D g_DepthLayer");
70 
71  _shader->addOutput("float outDepth");
72  }
73 
74  void modifyFragmentBeginCode(QStringList* _code)
75  {
76  // compare current depth with previous layer
77  _code->push_back("float dp_prevDepth = texture(g_DepthLayer, sg_vScreenPos).x;");
78  _code->push_back("if (gl_FragCoord.z <= dp_prevDepth) discard;");
79  }
80 
81  void modifyFragmentEndCode(QStringList* _code)
82  {
83  _code->push_back("outFragment = vec4(sg_cColor.rgb * sg_cColor.a, sg_cColor.a);");
84  _code->push_back("outDepth = gl_FragCoord.z;");
85  }
86 
87  static PeelLayerModifier instance;
88 };
89 
90 
92 {
93 public:
94 
96  {
97  _shader->addOutput("float outDepth");
98  }
99 
100  void modifyFragmentEndCode(QStringList* _code)
101  {
102  _code->push_back("outFragment = vec4(sg_cColor.rgb * sg_cColor.a, 1.0 - sg_cColor.a);");
103  _code->push_back("outDepth = gl_FragCoord.z;");
104  }
105 
106  static PeelInitModifier instance;
107 };
108 
109 // for dual depth peeling only
111 {
112 public:
113 
115  {
116  _shader->addUniform("sampler2D g_DepthLayer");
117  _shader->addUniform("sampler2D g_FrontLayer");
118 
119  // MRT: color + depth output + last layer (eventually)
120  _shader->addOutput("vec4 outDepth");
121  _shader->addOutput("vec4 outBackColor");
122  }
123 
124  void modifyFragmentBeginCode(QStringList* _code)
125  {
126  _code->push_back("float fragDepth = gl_FragCoord.z;");
127 
128 #ifdef __APPLE__
129  if(ACG::openGLVersion(3,3))
130  {
131  //on Apple systems with OpenGL 3.3 or higher, ht eGLSL version 330 is used no matter what we write
132  _code->push_back("vec2 depthLayer = texture(g_DepthLayer, sg_vScreenPos).xy;");
133  _code->push_back("vec4 forwardTemp = texture(g_FrontLayer, sg_vScreenPos);");
134  }
135  else
136 #endif
137  {
138  _code->push_back("vec2 depthLayer = texture2D(g_DepthLayer, sg_vScreenPos).xy;");
139  _code->push_back("vec4 forwardTemp = texture2D(g_FrontLayer, sg_vScreenPos);");
140  }
141  _code->push_back("outDepth = vec4(depthLayer, 0, 0);");
142  _code->push_back("outFragment = forwardTemp;");
143  _code->push_back("outBackColor = vec4(0,0,0,0);");
144 
145 
146  _code->push_back("float nearestDepth = -depthLayer.x;");
147  _code->push_back("float farthestDepth = depthLayer.y;");
148  _code->push_back("float alphaMultiplier = 1.0 - forwardTemp.w;");
149 
150 
151  _code->push_back("if (fragDepth < nearestDepth || fragDepth > farthestDepth) {");
152  _code->push_back("outDepth = vec4(-1,-1,-1,-1);");
153  _code->push_back("return;");
154  _code->push_back("}");
155 
156  _code->push_back("if (fragDepth > nearestDepth && fragDepth < farthestDepth) {");
157  _code->push_back("outDepth = vec4(-fragDepth, fragDepth, 0, 0);");
158  _code->push_back("return;");
159  _code->push_back("}");
160  }
161 
162 
163  void modifyFragmentEndCode(QStringList* _code)
164  {
165  _code->push_back("outDepth = vec4(-1,-1,-1,-1);");
166  _code->push_back("outFragment = forwardTemp;");
167 
168  _code->push_back("if (fragDepth == nearestDepth) {");
169  _code->push_back("outFragment.xyz += sg_cColor.rgb * sg_cColor.a * alphaMultiplier;");
170  _code->push_back("outFragment.w = 1.0 - alphaMultiplier * (1.0 - sg_cColor.a);");
171 
172 // _code->push_back("outFragment = vec4(alphaMultiplier,alphaMultiplier,alphaMultiplier,1);");
173 
174  _code->push_back("} else {");
175  _code->push_back("outBackColor += sg_cColor;");
176  _code->push_back("}");
177  }
178 
179  static PeelDualLayerModifier instance;
180 };
181 
183 {
184 public:
185  void modifyFragmentEndCode(QStringList* _code)
186  {
187  _code->push_back("outFragment = vec4(-gl_FragCoord.z, gl_FragCoord.z, 0, 0);");
188  }
189 
190  static PeelDualInitModifier instance;
191 };
192 
193 
194 PeelInitModifier PeelInitModifier::instance;
195 PeelLayerModifier PeelLayerModifier::instance;
196 PeelDualLayerModifier PeelDualLayerModifier::instance;
197 PeelDualInitModifier PeelDualInitModifier::instance;
198 
199 // internal shader-attribute flags
200 
201 #define RENDERFLAG_ALLOW_PEELING 1
202 
203 
204 // =================================================
205 
206 DepthPeeling::DepthPeeling()
207  : peelMode_(1), copyFrontDepth_(1), maxPeelCount_(20), peelBlend_(0), peelFinal_(0), peelQueryID_(0),
208 peelBlendDual_(0), peelFinalDual_(0)
209 {
210 }
211 
212 
213 DepthPeeling::~DepthPeeling()
214 {
215 }
216 
217 
218 
219 QString DepthPeeling::checkOpenGL()
220 {
221  //if(!ACG::compatibilityProfile())
222  // return QString("DepthPeeling render-plugin is nto yet compatible with core profile contexts.");
223  if (!ACG::openGLVersion(3, 2))
224  return QString("Insufficient OpenGL Version! OpenGL 3.2 or higher required");
225 
226  //no other extensions are necessary, as OpenGL version 3.2 includes them all in the spec
227 
228  return QString("");
229 }
230 
231 
232 void DepthPeeling::initializePlugin()
233 {
234  ACG::ShaderProgGenerator::setShaderDir(OpenFlipper::Options::shaderDirStr());
235 }
236 
237 void DepthPeeling::exit()
238 {
239  delete peelBlend_;
240  peelBlend_ = 0;
241 
242  delete peelFinal_;
243  peelFinal_ = 0;
244 
245  delete peelBlendDual_;
246  peelBlendDual_ = 0;
247 
248  delete peelFinalDual_;
249  peelFinalDual_ = 0;
250 
251  if (peelQueryID_)
252  glDeleteQueries(1, &peelQueryID_);
253  peelQueryID_ = 0;
254 
255  viewerRes_.clear();
256 }
257 
258 void DepthPeeling::slotModeChanged( QAction * _action)
259 {
260  // Prepare Picking Debugger Flag
261  if ( _action->text() == "Front to Back") {
262  peelMode_ = 0;
263  } else if ( _action->text() == "Dual") {
264  peelMode_ = 1;
265  } else {
266  std::cerr << "Error : optionHandling unable to find peeling mode!!! " << _action->text().toStdString() << std::endl;
267  peelMode_ = 1;
268  }
269 }
270 
271 void DepthPeeling::render(ACG::GLState* _glState, Viewer::ViewerProperties& _properties)
272 {
273  // debugging utilities
274 // if (!dbgProg_)
275 // dbgProg_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/dbg_shader.glsl");
276 
277 
278  // collect renderobjects
279  prepareRenderingPipeline(_glState, _properties.drawMode(), PluginFunctions::getSceneGraphRootNode());
280 
281 
282  if (peelMode_ == 0)
283  renderFrontPeeling(_glState, _properties);
284  else
285  renderDualPeeling(_glState, _properties);
286 
287  // restore common opengl state
288  // log window remains hidden otherwise
289  finishRenderingPipeline();
290 }
291 
292 
293 
294 
295 
297  Viewer::ViewerProperties& _properties)
298 {
299  const int numRenderObjects = getNumRenderObjects();
300 
301  // begin rendering
302  // find last transparent object
303  int lastPeeledObject = -1;
304 
305  for (int i = numRenderObjects - 1; i > lastPeeledObject; --i)
306  {
307  if ((sortedObjects_[i]->internalFlags_ & RENDERFLAG_ALLOW_PEELING) && sortedObjects_[i]->alpha < 0.99f)
308  lastPeeledObject = i;
309  }
310 
311  if (lastPeeledObject == -1)
312  {
313  // no transparent objects
314  for (int i = 0; i < numRenderObjects; ++i)
315  renderObject(sortedObjects_[i]);
316  }
317  else
318  {
319  // depth peeling code
320 
321  // make sure shaders and occlusion query are initialized
322  initDepthPeeling();
323 
324  // resize fbo as necessary
325  ViewerResources* viewRes = &viewerRes_[_properties.viewerId()];
326  viewRes->resize(false, (unsigned int)_glState->viewport_width(), (unsigned int)_glState->viewport_height());
327 
328 
329  // init MRT slots:
330  // RT0 - color blend texture
331  // RT1 - depth buffer copy
332  const GLenum depthTarget = GL_COLOR_ATTACHMENT0;
333  const GLenum colorTarget = GL_COLOR_ATTACHMENT1;
334  const GLenum colorBlendTarget = GL_COLOR_ATTACHMENT4;
335  GLenum peelLayerTargets[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
336 
337  const float clearDepth = 1.0f;
338 
339  // begin peeling
340  // draw first layer
341  // target depth buffer: depth0, front0
342  glViewport(0, 0, viewRes->width_, viewRes->height_);
343  glBindFramebuffer(GL_FRAMEBUFFER, viewRes->singleFbo_->getFboID());
344 
345  // allow color+depth write access
346  glDepthMask(1);
347  glColorMask(1,1,1,1);
348 
349  // clear color blend target
350  glDrawBuffer(colorBlendTarget);
351  glClearColor(_glState->clear_color()[0], _glState->clear_color()[1], _glState->clear_color()[2], 0);
352  glClear(GL_COLOR_BUFFER_BIT);
353 
354  // clear colors (front and back colors per pass)
355  glDrawBuffer(colorTarget);
356  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
357  glClear(GL_COLOR_BUFFER_BIT);
358 
359  // clear depths
360  glDrawBuffer(depthTarget);
361  glClearColor(clearDepth, 0.0f, 0.0f, 0.0f);
362  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
363 
364 
365  // 1. Pass: initialize depth values
366  // the init shader also writes the first front layer colors in accumulation buffer
367  peelLayerTargets[0] = colorBlendTarget;
368  peelLayerTargets[1] = depthTarget;
369  glDrawBuffers(2, peelLayerTargets); // write to MRT slots (color, depth)
370 
371  glDisable(GL_BLEND);
372  glDisable(GL_ALPHA_TEST);
373 
374  glEnable(GL_DEPTH_TEST);
375  glDepthFunc(GL_LESS);
376  glDisable(GL_CULL_FACE);
377 
378  for (int i = 0; i < numRenderObjects; ++i)
379  {
380 // if ((sortedObjects_[i]->internalFlags_ & RENDERFLAG_ALLOW_PEELING) && sortedObjects_[i]->alpha < 0.99f)
381  {
382  GLSL::Program* initProg = ShaderCache::getInstance()->getProgram(&sortedObjects_[i]->shaderDesc, PeelInitModifier::instance);
383 
384  if (initProg->getFragDataLocation("outFragment") != 0 || initProg->getFragDataLocation("outDepth") != 1)
385  {
386  initProg->bindFragDataLocation(0, "outFragment"); // color -> slot0
387  initProg->bindFragDataLocation(1, "outDepth"); // depth -> slot1
388  initProg->link();
389  }
390 
391  renderObject(sortedObjects_[i], initProg, true);
392  }
393  }
394 
395  // copy depth values to input depth buffer if requested
396  if (copyFrontDepth_)
397  copyDepthToBackBuffer(viewRes->singleDepthTex_[0], 1.0f);
398 
399  // peel layers, we start at index 1 instead of 0
400  // since the front layer is already initialized in
401  // depth buffer 0 and we want to extract the second one now
402 
403  for (int pass = 1; pass < maxPeelCount_; ++pass)
404  {
405  const int currID = pass & 1;
406  const int prevID = 1 - currID;
407  const int bufID = currID * 2;
408 
409  // peeling MRT slots:
410  // RT0 - color
411  // RT1 - depth buffer copy
412  const GLenum targetBuffer[2] = {colorTarget + bufID, depthTarget + bufID};
413 
414  // ---------------------------------------------------------------
415  // 1st peel next layer
416 
417  // clear color texture
418  glDrawBuffer(targetBuffer[0]);
419  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
420  glClear(GL_COLOR_BUFFER_BIT);
421  // clear depth texture
422  glDrawBuffer(targetBuffer[1]);
423  glClearColor(clearDepth, 0.0f, 0.0f, 0.0f);
424  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
425 
426 
427  glDrawBuffers(2, targetBuffer);
428 
429 
430  glDisable(GL_BLEND);
431  glEnable(GL_DEPTH_TEST);
432 
433  // count # passed fragments
434  glBeginQuery(GL_SAMPLES_PASSED, peelQueryID_);
435 
436 
437  // bind previous depth layer to texture unit 4
438  glActiveTexture(GL_TEXTURE4);
439  glBindTexture(GL_TEXTURE_2D, viewRes->singleDepthTex_[prevID]);
440 
441  // render scene
442  for (int k = 0; k < numRenderObjects; ++k)
443  {
444  if ((sortedObjects_[k]->internalFlags_ & RENDERFLAG_ALLOW_PEELING) && sortedObjects_[k]->alpha < 0.99f)
445  {
446  GLSL::Program* peelProg = ShaderCache::getInstance()->getProgram(&sortedObjects_[k]->shaderDesc, PeelLayerModifier::instance);
447 
448  if (peelProg->getFragDataLocation("outFragment") != 0 || peelProg->getFragDataLocation("outDepth") != 1)
449  {
450  peelProg->bindFragDataLocation(0, "outFragment");
451  peelProg->bindFragDataLocation(1, "outDepth");
452  peelProg->link();
453  }
454 
455  peelProg->use();
456  peelProg->setUniform("g_DepthLayer", 4);
457 
458  renderObject(sortedObjects_[k], peelProg, true);
459  }
460  }
461 
462  glEndQuery(GL_SAMPLES_PASSED);
463 
464 
465 
466  // ---------------------------------------------------------------
467  // 2nd underblend layer with current scene
468  // (fullscreen pass)
469  glDrawBuffer(colorBlendTarget);
470 
471  glDepthMask(1);
472  glColorMask(1,1,1,1);
473 
474  glDisable(GL_DEPTH_TEST);
475  glEnable(GL_BLEND);
476 
477  glBlendEquation(GL_FUNC_ADD);
478  ACG::GLState::blendFuncSeparate(GL_DST_ALPHA, GL_ONE,
479  GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
480 
481 
482  peelBlend_->use();
483  peelBlend_->setUniform("BlendTex", 0);
484 
485  glActiveTexture(GL_TEXTURE0);
486  glBindTexture(GL_TEXTURE_2D, viewRes->singleFrontTex_[currID]);
487 
488  ACG::ScreenQuad::draw(peelBlend_);
489 
490 
491  glDisable(GL_BLEND);
492 
493 
494 
495  GLuint passedSamples;
496  glGetQueryObjectuiv(peelQueryID_, GL_QUERY_RESULT, &passedSamples);
497  if (passedSamples == 0)
498  break;
499  }
500 
501 
502  // copy to back buffer
503  restoreInputFbo();
504 
505  glDepthMask(1);
506  glColorMask(1,1,1,1);
507 
508  glDisable(GL_DEPTH_TEST);
509 
510  peelFinal_->use();
511 
512 
513  ACG::Vec3f bkgColor;
514  bkgColor[0] = _properties.backgroundColor()[0];
515  bkgColor[1] = _properties.backgroundColor()[1];
516  bkgColor[2] = _properties.backgroundColor()[2];
517 
518  peelFinal_->setUniform("BkgColor", bkgColor);
519 
520  peelFinal_->setUniform("SceneTex", 0);
521 
522  glActiveTexture(GL_TEXTURE0);
523  glBindTexture(GL_TEXTURE_2D, viewRes->singleBlendTex_);
524 
525  ACG::ScreenQuad::draw(peelFinal_);
526 
528 
529 
530 
531 
532  // draw rest of scene
533  glEnable(GL_DEPTH_TEST);
534 
535 
536 // // draw rest of opaque objects
537 // for (int i = lastPeeledObject + 1; i < numRenderObjects; ++i)
538 // renderObject(sortedObjects_[i]);
539 
540  }
541 }
542 
543 
545 {
546  const int numRenderObjects = getNumRenderObjects();
547 
548  // begin rendering
549  // find last transparent object
550  int lastPeeledObject = -1;
551 
552  for (int i = numRenderObjects - 1; i > lastPeeledObject; --i)
553  {
554  if ((sortedObjects_[i]->internalFlags_ & RENDERFLAG_ALLOW_PEELING) && sortedObjects_[i]->alpha < 0.99f)
555  lastPeeledObject = i;
556  }
557 
558  if (0) //lastPeeledObject == -1)
559  {
560  // no transparent objects
561  for (int i = 0; i < numRenderObjects; ++i)
562  renderObject(sortedObjects_[i]);
563  }
564  else
565  {
566  // depth peeling code
567 
568  // make sure shaders and occlusion query are initialized
569  initDualDepthPeeling();
570 
571  // resize fbo as necessary
572  ViewerResources* viewRes = &viewerRes_[_properties.viewerId()];
573  viewRes->resize(true, (unsigned int)_glState->viewport_width(), (unsigned int)_glState->viewport_height());
574 
575 
576  // enable color/depth write access
577  glDepthMask(1);
578  glColorMask(1,1,1,1);
579 
580 
581  // clear render targets
582 // viewRes->dualFboACG_->bind();
583  glViewport(0, 0, _glState->viewport_width(), _glState->viewport_height());
584  glBindFramebuffer(GL_FRAMEBUFFER, viewRes->dualFbo_->getFboID());
585 
586  const GLenum depthTarget = GL_COLOR_ATTACHMENT0; // stores (-minDepth, maxDepth)
587  const GLenum colorTargets[] = {GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
588  const GLenum colorBlendTarget = GL_COLOR_ATTACHMENT6;
589 
590  // clear colors (front and back colors per pass)
591  glDrawBuffers(2, colorTargets);
592  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
593  glClear(GL_COLOR_BUFFER_BIT);
594 
595  // clear color blend target
596  glDrawBuffer(colorBlendTarget);
597  glClearColor(_glState->clear_color()[0], _glState->clear_color()[1], _glState->clear_color()[2], 0);
598  glClear(GL_COLOR_BUFFER_BIT);
599 
600  // clear depths
601  glDrawBuffer(depthTarget);
602  glClearColor(-1.0f, -1.0f, 0.0f, 0.0f);
603  glClear(GL_COLOR_BUFFER_BIT);
604 
605 
606  // 1. Pass: initialize depth values
607  // the init shader writes min/max depth values (-z, +z)
608  glEnable(GL_BLEND);
609  glBlendEquation(GL_MAX_EXT); // get min/max depth
610 
611  if(_glState->compatibilityProfile())
612  glDisable(GL_ALPHA_TEST);
613 
614  glEnable(GL_DEPTH_TEST);
615  glDepthFunc(GL_LESS);
616  glDisable(GL_CULL_FACE);
617 
618  for (int i = 0; i < numRenderObjects; ++i)
619  {
620  GLSL::Program* initProg = ShaderCache::getInstance()->getProgram(&sortedObjects_[i]->shaderDesc, PeelDualInitModifier::instance);
621 
622  renderObject(sortedObjects_[i], initProg, true);
623  }
624 
625 
626  // copy depth values of first front layer to input depth buffer if requested
627  if (copyFrontDepth_)
628  {
629  glDisable(GL_BLEND);
630  copyDepthToBackBuffer(viewRes->dualDepthTex_[0], -1.0f);
631  // dual peeling requires blending
632  glEnable(GL_BLEND);
633  }
634 
635  // 2. peeling passes + color accumulation
636 
637  int currID = 0; // ping-pong render targets
638 
639 //if (0){
640 
641  for (int pass = 1; 1 && pass < maxPeelCount_; ++pass)
642  {
643  currID = pass & 1;
644  const int prevID = 1 - currID;
645  const int bufID = currID * 3;
646 
647  GLenum targetBuffer[3];
648  targetBuffer[0] = GL_COLOR_ATTACHMENT0 + bufID;
649  targetBuffer[1] = GL_COLOR_ATTACHMENT1 + bufID;
650  targetBuffer[2] = GL_COLOR_ATTACHMENT2 + bufID;
651 // GLenum sourceBuffer[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
652 
653  // clear target colors
654  glDrawBuffers(2, targetBuffer + 1);
655  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
656  glClear(GL_COLOR_BUFFER_BIT);
657 
658  // clear target depth
659  glDrawBuffer(targetBuffer[0]);
660  glClearColor(-1.0f, -1.0f, 0.0f, 0.0f);
661  glClear(GL_COLOR_BUFFER_BIT);
662 
663 
664 
665  // Peel pass
666 
667  // set target
668  glBlendEquation(GL_MAX_EXT);
669  glDrawBuffers(3, targetBuffer); // shader writes to (depth_tex, front_color_tex, back_color_tex)
670 
671  // set texture source (provide previous layer)
672  // slot 4 - depth
673  // slot 5 - front color
674 
675  glActiveTexture(GL_TEXTURE5);
676  glBindTexture(GL_TEXTURE_2D, viewRes->dualFrontTex_[prevID]);
677 
678  glActiveTexture(GL_TEXTURE4);
679  glBindTexture(GL_TEXTURE_2D, viewRes->dualDepthTex_[prevID]);
680 
681  // restore active tex marker to default slot
682  glActiveTexture(GL_TEXTURE0);
683 
684  // peel scene
685  for (int i = 0; i < numRenderObjects; ++i)
686  {
687  GLSL::Program* peelProg = ShaderCache::getInstance()->getProgram(&sortedObjects_[i]->shaderDesc, PeelDualLayerModifier::instance);
688 
689  peelProg->use();
690  peelProg->setUniform("g_DepthLayer", 4);
691  peelProg->setUniform("g_FrontLayer", 5);
692 
693  // setup MRT
694  // outFragment -> front
695  // outDepth -> depth
696  // outBackColor -> back
697 
698  int locOutFrag = peelProg->getFragDataLocation("outFragment");
699  int locOutDepth = peelProg->getFragDataLocation("outDepth");
700  int locOutBackColor = peelProg->getFragDataLocation("outBackColor");
701 
702  if (locOutFrag != 1 ||
703  locOutDepth != 0 ||
704  locOutBackColor != 2)
705  {
706  // linking is slow; only link if necessary
707  peelProg->bindFragDataLocation(1, "outFragment");
708  peelProg->bindFragDataLocation(0, "outDepth");
709  peelProg->bindFragDataLocation(2, "outBackColor");
710 
711  peelProg->link();
712  }
713 
714 
715 
716  renderObject(sortedObjects_[i], peelProg, true);
717  }
718 
719 
720 
721 
722  // ----------------------
723  // debugging
724 /*
725  if (pass == 1)
726  {
727  dbgDrawTex(viewRes->dualFrontTex_[currID]);
728  return;
729  }
730 */
731  //
732 
733 
734 
735 
736  // blend back color into accumulation buffer
737  glDrawBuffer(colorBlendTarget);
738 
739  glBlendEquation(GL_FUNC_ADD);
740  ACG::GLState::blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
741 
742  // bind back color texture to slot 0
743  glActiveTexture(GL_TEXTURE0);
744  glBindTexture(GL_TEXTURE_2D, viewRes->dualBackTex_[currID]);
745 
746 
747  glBeginQuery(GL_SAMPLES_PASSED_ARB, peelQueryID_);
748 
749  peelBlendDual_->use();
750  peelBlendDual_->setUniform("BlendTex", 0);
751 
752  ACG::ScreenQuad::draw(peelBlendDual_);
753 
754  glEndQuery(GL_SAMPLES_PASSED_ARB);
755 
756 
757 
758  // termination check
759  GLuint passedSamples;
760  glGetQueryObjectuiv(peelQueryID_, GL_QUERY_RESULT, &passedSamples);
761  if (passedSamples == 0)
762  break;
763  }
764 
765 //}
766 
767  // Final pass: combine accumulated front and back colors
768  restoreInputFbo();
769 
770  glDepthMask(1);
771  glColorMask(1,1,1,1);
772 
773  glDisable(GL_DEPTH_TEST);
774  glDisable(GL_BLEND);
775 
776 
777  peelFinalDual_->use();
778 
779 
780  ACG::Vec3f bkgColor;
781  bkgColor[0] = _properties.backgroundColor()[0];
782  bkgColor[1] = _properties.backgroundColor()[1];
783  bkgColor[2] = _properties.backgroundColor()[2];
784 
785  peelFinalDual_->setUniform("BkgColor", bkgColor);
786 
787  // slot 0 - front colors
788  // slot 1 - back colors
789 
790  peelFinalDual_->setUniform("FrontSceneTex", 0);
791  peelFinalDual_->setUniform("BackSceneTex", 1);
792 
793  glActiveTexture(GL_TEXTURE1);
794  glBindTexture(GL_TEXTURE_2D, viewRes->dualBlendTex_);
795 
796  glActiveTexture(GL_TEXTURE0);
797  glBindTexture(GL_TEXTURE_2D, viewRes->dualFrontTex_[currID]);
798 
799 // drawProjQuad(peelFinalDual_);
800  ACG::ScreenQuad::draw(peelFinalDual_);
801 
802 
803  peelFinalDual_->disable();
804 
805 
806 
807 
808 
809  // ------------------------------------------
810  // debugging
811 
812 // dbgDrawTex(viewRes->dualDepthTex_[0]);
813 
814 
815  // ------------------------------------------
816 
817 
818 
819 
820 
821 
822 
823 
825 
826 
827 // // draw rest of scene
828 // glEnable(GL_DEPTH_TEST);
829 //
830 //
831 // // draw rest of opaque objects
832 // for (int i = lastPeeledObject + 1; i < numRenderObjects; ++i)
833 // renderObject(sortedObjects_[i]);
834 
835  }
836 }
837 
839 {
840  // do some more checks for error detection
841  if (!_renderObject->vertexDecl)
842  std::cout << "error: missing vertex declaration" << std::endl;
843  else
844  {
845  renderObjects_.push_back(*_renderObject);
846 
847 
848  RenderObject* p = &renderObjects_.back();
849 
850  if (!p->shaderDesc.numLights)
851  p->shaderDesc.numLights = numLights_;
852 
853  else if (p->shaderDesc.numLights < 0 || p->shaderDesc.numLights >= SG_MAX_SHADER_LIGHTS)
854  p->shaderDesc.numLights = 0;
855 
856  p->internalFlags_ = 0;
857 
858  // allow potential depth peeling only for compatible
859  // render states
860 
861  if (p->alpha < 1.0f &&
862  p->depthTest &&
863  p->depthWrite && (p->depthFunc == GL_LESS ||
864  p->depthFunc == GL_LEQUAL))
865  p->internalFlags_ = RENDERFLAG_ALLOW_PEELING;
866 
867 
868  // precompile shader
870 
871  }
872 }
873 
874 
875 
876 
877 DepthPeeling::ViewerResources::ViewerResources()
878 : width_(0), height_(0), singleBlendTex_(0), singleFbo_(0), dualBlendTex_(0), dualFbo_(0)
879 {
880  memset(singleDepthTex_, 0, sizeof(singleDepthTex_));
881  memset(singleFrontTex_, 0, sizeof(singleFrontTex_));
882 
883  memset(dualDepthTex_, 0, sizeof(dualDepthTex_));
884  memset(dualFrontTex_, 0, sizeof(dualFrontTex_));
885  memset(dualBackTex_, 0, sizeof(dualBackTex_));
886 }
887 
888 
889 DepthPeeling::ViewerResources::~ViewerResources()
890 {
891  delete singleFbo_;
892  delete dualFbo_;
893 }
894 
895 
896 void DepthPeeling::ViewerResources::resize(bool _dualPeeling, unsigned int _width, unsigned int _height)
897 {
898  if (!_width || !_height)
899  return;
900 
901  width_ = _width;
902  height_ = _height;
903 
904  if (!_dualPeeling)
905  {
906  if (!singleFbo_)
907  {
908  singleFbo_ = new ACG::FBO();
909 
910  singleFbo_->init();
911 
912  // texture formats:
913  // depth textures: store layer depth as float
914  // front color textures: store (r,g,b,a) colors as R8G8B8A8
915  // color blending and accumulation texture: (r,g,b,a) color as R8G8B8A8
916  GLint wrapmode;
917  if(ACG::openGLVersion(3,2))
918  wrapmode = GL_CLAMP_TO_EDGE;
919  else
920  wrapmode = GL_CLAMP;
921 
922  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT0, width_, height_, GL_R32F, GL_RGB, wrapmode, GL_NEAREST, GL_NEAREST);
923  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT1, width_, height_, GL_RGBA, GL_RGBA, wrapmode, GL_NEAREST, GL_NEAREST);
924 
925  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT2, width_, height_, GL_R32F, GL_RGB, wrapmode, GL_NEAREST, GL_NEAREST);
926  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT3, width_, height_, GL_RGBA, GL_RGBA, wrapmode, GL_NEAREST, GL_NEAREST);
927 
928  singleFbo_->attachTexture2D(GL_COLOR_ATTACHMENT4, width_, height_, GL_RGBA, GL_RGBA, wrapmode, GL_NEAREST, GL_NEAREST);
929 
930  singleFbo_->attachTexture2DDepth(width_, height_);
931 
932  singleDepthTex_[0] = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT0);
933  singleDepthTex_[1] = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT2);
934 
935  singleFrontTex_[0] = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT1);
936  singleFrontTex_[1] = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT3);
937 
938  singleBlendTex_ = singleFbo_->getAttachment(GL_COLOR_ATTACHMENT4);
939 
940 
941  singleFbo_->checkFramebufferStatus();
942 
944  }
945  else
946  singleFbo_->resize(_width, _height);
947 
948  }
949  else
950  {
951  // dual peeling render targets
952 
953  // fbo
954  if (!dualFbo_)
955  {
956  dualFbo_ = new ACG::FBO();
957 
958  dualFbo_->init();
959 
960  // texture formats:
961  // depth textures: store (min,max) depth as float2
962  // front+back color textures: store (r,g,b,a) colors as R8G8B8A8
963  // color blending and accumulation texture: (r,g,b) color as R8G8B8X8
964  GLint wrapmode;
965  if(ACG::openGLVersion(3,2))
966  {
967  wrapmode = GL_CLAMP_TO_EDGE;
968  }
969  else
970  wrapmode = GL_CLAMP;
971  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT0, width_, height_, GL_RG32F, GL_RGB, wrapmode, GL_NEAREST, GL_NEAREST);
972  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT1, width_, height_, GL_RGBA, GL_RGBA, wrapmode, GL_NEAREST, GL_NEAREST);
973  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT2, width_, height_, GL_RGBA, GL_RGBA, wrapmode, GL_NEAREST, GL_NEAREST);
974 
975  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT3, width_, height_, GL_RG32F, GL_RGB, wrapmode, GL_NEAREST, GL_NEAREST);
976  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT4, width_, height_, GL_RGBA, GL_RGBA, wrapmode, GL_NEAREST, GL_NEAREST);
977  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT5, width_, height_, GL_RGBA, GL_RGBA, wrapmode, GL_NEAREST, GL_NEAREST);
978 
979  dualFbo_->attachTexture2D(GL_COLOR_ATTACHMENT6, width_, height_, GL_RGB, GL_RGB, wrapmode, GL_NEAREST, GL_NEAREST);
980 
981  dualDepthTex_[0] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT0);
982  dualDepthTex_[1] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT3);
983 
984  dualFrontTex_[0] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT1);
985  dualFrontTex_[1] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT4);
986 
987  dualBackTex_[0] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT2);
988  dualBackTex_[1] = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT5);
989 
990  dualBlendTex_ = dualFbo_->getAttachment(GL_COLOR_ATTACHMENT6);
991 
992 
993  dualFbo_->checkFramebufferStatus();
994 
996  }
997  else
998  dualFbo_->resize(_width, _height);
999 
1000  }
1001 
1002 
1003  glBindFramebuffer(GL_FRAMEBUFFER, 0);
1004 
1006 }
1007 
1009 {
1010  // check if already initialized
1011  if (peelBlend_ && peelFinal_ && peelQueryID_)
1012  return;
1013 
1014  // register shader modifiers
1015  ShaderProgGenerator::registerModifier(&PeelInitModifier::instance);
1016  ShaderProgGenerator::registerModifier(&PeelLayerModifier::instance);
1017 
1018  // load intermediate blending and final shader
1019 #ifdef __APPLE__
1020  if(ACG::openGLVersion(3,3))
1021  {
1022  if (!peelBlend_)
1023  peelBlend_ = GLSL::loadProgram("DepthPeeling/screenquad_330.glsl", "DepthPeeling/blend_330.glsl");
1024 
1025  if (!peelFinal_)
1026  peelFinal_ = GLSL::loadProgram("DepthPeeling/screenquad_330.glsl", "DepthPeeling/final_330.glsl");
1027  }
1028  else
1029 #endif
1030  {
1031  if (!peelBlend_)
1032  peelBlend_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/blend.glsl");
1033 
1034  if (!peelFinal_)
1035  peelFinal_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/final.glsl");
1036  }
1037 
1038  // occ query id
1039  if (!peelQueryID_)
1040  glGenQueries(1, &peelQueryID_);
1041 
1043 }
1044 
1046 {
1047  // check if already initialized
1048  if (peelBlendDual_ && peelFinalDual_ && peelQueryID_)
1049  return;
1050 
1051  // register shader modifiers
1052  ShaderProgGenerator::registerModifier(&PeelDualInitModifier::instance);
1053  ShaderProgGenerator::registerModifier(&PeelDualLayerModifier::instance);
1054 
1055  // load intermediate blending and final shader
1056 #ifdef __APPLE__ //this is fugly, pimpl pattern would be much appreciated
1057  if(ACG::openGLVersion(3,3))
1058  {
1059  if(!peelBlendDual_)
1060  peelBlendDual_ = GLSL::loadProgram("DepthPeeling/screenquad_330.glsl", "DepthPeeling/blend_dual_330.glsl");
1061  if (!peelFinalDual_)
1062  peelFinalDual_ = GLSL::loadProgram("DepthPeeling/screenquad_330.glsl", "DepthPeeling/final_dual_330.glsl");
1063  }
1064  else
1065 #endif
1066  {
1067  if(!peelBlendDual_)
1068  peelBlendDual_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/blend_dual.glsl");
1069  if (!peelFinalDual_)
1070  peelFinalDual_ = GLSL::loadProgram("DepthPeeling/screenquad.glsl", "DepthPeeling/final_dual.glsl");
1071  }
1072 
1073  // occ query id
1074  if (!peelQueryID_)
1075  glGenQueries(1, &peelQueryID_);
1076 
1078 }
1079 
1080 QString DepthPeeling::renderObjectsInfo( bool _outputShaderInfo )
1081 {
1082  QString infoString;
1083 
1084  ACG::ShaderModifier* availableMods[4] =
1085  {
1086  &PeelInitModifier::instance, &PeelLayerModifier::instance,
1087  &PeelDualInitModifier::instance, &PeelDualLayerModifier::instance
1088  };
1089 
1090 
1091  // write modified shaders for init and peel passes
1092 
1093  infoString += "PeelInit:\n\n\n";
1094 
1095  std::vector<ACG::ShaderModifier*> mods;
1096  mods.push_back(availableMods[peelMode_*2]);
1097 
1098  infoString += dumpCurrentRenderObjectsToString(&sortedObjects_[0],_outputShaderInfo, &mods);
1099 
1100 
1101  infoString += "\n\n-----------------------------------------------\n\n\n\n";
1102  infoString += "PeelLayer:\n\n\n";
1103 
1104  mods[0] = availableMods[peelMode_*2 + 1];
1105 
1106  infoString += dumpCurrentRenderObjectsToString(&sortedObjects_[0],_outputShaderInfo, &mods);
1107 
1108  return infoString;
1109 }
1110 
1111 
1112 //
1113 // void DepthPeeling::dbgDrawTex( GLuint _texID )
1114 // {
1115 // glBindFramebuffer(GL_FRAMEBUFFER, 0);
1116 // glDrawBuffer(GL_BACK);
1117 // glClearColor(0,0,0,0);
1118 // glClear(GL_COLOR_BUFFER_BIT);
1119 //
1120 //
1121 // glDepthMask(1);
1122 // glColorMask(1,1,1,1);
1123 //
1124 // glDisable(GL_DEPTH_TEST);
1125 // glDisable(GL_BLEND);
1126 //
1127 // dbgProg_->use();
1128 //
1129 // dbgProg_->setUniform("Tex", 0);
1130 //
1131 // glActiveTexture(GL_TEXTURE0);
1132 // glBindTexture(GL_TEXTURE_2D, _texID);
1133 //
1134 // drawProjQuad(dbgProg_);
1135 //
1136 // dbgProg_->disable();
1137 // }
1138 //
1139 
1140 
1141 
1142 
unsigned int width_
viewer window width
static void setShaderDir(QString _dir)
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:84
Namespace providing different geometric functions concerning angles.
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
void addOutput(const QString &_output)
Add one GLSL output specifier.
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:102
GLuint getFboID()
return opengl id
Definition: FBO.cc:604
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
void addUniform(QString _uniform, QString _comment="")
Add one GLSL uniform specifier.
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:692
int viewport_width() const
get viewport width
Definition: GLState.hh:822
QString renderObjectsInfo(bool _outputShaderInfo)
Return a qstring of the current render objects.
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:921
unsigned int height_
viewer window height
static void blendFuncSeparate(GLenum _srcRGB, GLenum _dstRGB, GLenum _srcAlpha, GLenum _dstAlpha)
replaces glBlendFuncSeparate, supports locking
Definition: GLState.cc:1621
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
GLSL program class.
Definition: GLSLShader.hh:211
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:307
void initDepthPeeling()
Allocate framebuffers and load shaders for depth-peeling.
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
Definition: DepthPeeling.cc:95
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
Definition: DepthPeeling.cc:81
void renderFrontPeeling(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
peel the scene from front to back, one layer per pass
unsigned int internalFlags_
may be used internally by the renderer
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:724
ACG::Vec4f backgroundColor()
Get current background color.
void initDualDepthPeeling()
Allocate framebuffers and load shaders for dual-depth-peeling.
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:326
int viewport_height() const
get viewport height
Definition: GLState.hh:824
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
Definition: DepthPeeling.cc:67
Definition: FBO.hh:71
void glCheckErrors()
Definition: GLError.hh:96
Collection of framebuffers for each viewport.
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
ShaderGenDesc shaderDesc
Drawmode and other shader params.
void addRenderObject(ACG::RenderObject *_renderObject)
overide addRenderObject function to include OIT check
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:138
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:1076
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:385
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
void renderDualPeeling(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
peel the scene with dual depth peeling, two layers per pass
void use()
Enables the program object for using.
Definition: GLSLShader.cc:345
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
Definition: DepthPeeling.cc:74
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129