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 addRenderObject(ACG::RenderObject *_renderObject)
overide addRenderObject function to include OIT check
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:1606
int viewport_width() const
get viewport width
Definition: GLState.hh:825
int maxPeelCount_
max peel count
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:147
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
unsigned int width_
viewer window width
virtual void finishRenderingPipeline(bool _drawOverlay=true)
Draw overlay objects and reset OpenGL state.
Definition: IRenderer.cc:654
int peelMode_
mode: 0 -> front to back peeling, 1 -> dual peeling
unsigned int height_
viewer window height
int numLights_
Number of Lights.
Definition: IRenderer.hh:497
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:332
void renderDualPeeling(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
peel the scene with dual depth peeling, two layers per pass
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
std::vector< ACG::RenderObject * > sortedObjects_
sorted list of renderobjects without overlay objects (sorted in rendering order)
Definition: IRenderer.hh:515
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
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:1250
void glCheckErrors()
Definition: GLError.hh:105
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:924
void initDepthPeeling()
Allocate framebuffers and load shaders for depth-peeling.
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:698
static void setShaderDir(QString _dir)
void addOutput(const QString &_output)
Add one GLSL output specifier.
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:314
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
Definition: DepthPeeling.cc:74
QString renderObjectsInfo(bool _outputShaderInfo)
Return a qstring of the current render objects.
GLuint peelQueryID_
occlusion query determining end of peeling (last layer)
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:1107
Definition: FBO.hh:83
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
Definition: DepthPeeling.cc:88
GLSL::Program * peelBlendDual_
dual depth peeling shaders
void initDualDepthPeeling()
Allocate framebuffers and load shaders for dual-depth-peeling.
Collection of framebuffers for each viewport.
GLSL program class.
Definition: GLSLShader.hh:217
std::vector< ACG::RenderObject > renderObjects_
array of renderobjects, filled by addRenderObject()
Definition: IRenderer.hh:507
int viewport_height() const
get viewport height
Definition: GLState.hh:827
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
void renderFrontPeeling(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
peel the scene from front to back, one layer per pass
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects) ...
Definition: IRenderer.cc:1179
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
Definition: DepthPeeling.cc:81
unsigned int internalFlags_
may be used internally by the renderer
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:529
void addUniform(QString _uniform, QString _comment="")
Add one GLSL uniform specifier.
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:73
Interface class between scenegraph and renderer.
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:730
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
GLSL::Program * peelBlend_
blends one depth-layer into the current scene target
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
virtual void copyDepthToBackBuffer(GLuint _depthTex, float _scale=1.0f)
Copy texture to depth buffer.
Definition: IRenderer.cc:1315
virtual void restoreInputFbo()
Restore the previously saved input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:768
GLuint getFboID()
return opengl id
Definition: FBO.cc:597
std::map< int, ViewerResources > viewerRes_
GLSL::Program * peelFinal_
final copy into back-buffer
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
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 disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:361
ACG::Vec4f backgroundColor()
Get current background color.
ShaderGenDesc shaderDesc
Drawmode and other shader params.
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.