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
56using namespace ACG;
57
58
59// =================================================
60// depth peeling shader modifier
61
63{
64public:
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{
93public:
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{
112public:
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{
184public:
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
194PeelInitModifier PeelInitModifier::instance;
195PeelLayerModifier PeelLayerModifier::instance;
196PeelDualLayerModifier PeelDualLayerModifier::instance;
197PeelDualInitModifier PeelDualInitModifier::instance;
198
199// internal shader-attribute flags
200
201#define RENDERFLAG_ALLOW_PEELING 1
202
203
204// =================================================
205
206DepthPeeling::DepthPeeling()
207 : peelMode_(1), copyFrontDepth_(1), maxPeelCount_(20), peelBlend_(0), peelFinal_(0), peelQueryID_(0),
208peelBlendDual_(0), peelFinalDual_(0)
209{
210}
211
212
213DepthPeeling::~DepthPeeling()
214{
215}
216
217
218
219QString 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
232void DepthPeeling::initializePlugin()
233{
234 ACG::ShaderProgGenerator::setShaderDir(OpenFlipper::Options::shaderDirStr());
235}
236
237void 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
258void 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
271void 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
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
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)
316 }
317 else
318 {
319 // depth peeling code
320
321 // make sure shaders and occlusion query are initialized
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
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
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
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)
563 }
564 else
565 {
566 // depth peeling code
567
568 // make sure shaders and occlusion query are initialized
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
750 peelBlendDual_->setUniform("BlendTex", 0);
751
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
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
869 ShaderCache::getInstance()->getProgram(&p->shaderDesc);
870
871 }
872}
873
874
875
876
877DepthPeeling::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
889DepthPeeling::ViewerResources::~ViewerResources()
890{
891 delete singleFbo_;
892 delete dualFbo_;
893}
894
895
896void 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
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
1080QString 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
Definition: FBO.hh:72
GLuint getFboID()
return opengl id
Definition: FBO.cc:604
int viewport_width() const
get viewport width
Definition: GLState.hh:847
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:307
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:946
int viewport_height() const
get viewport height
Definition: GLState.hh:849
static void blendFuncSeparate(GLenum _srcRGB, GLenum _dstRGB, GLenum _srcAlpha, GLenum _dstAlpha)
replaces glBlendFuncSeparate, supports locking
Definition: GLState.cc:1621
std::vector< ACG::RenderObject * > sortedObjects_
sorted list of renderobjects without overlay objects (sorted in rendering order)
Definition: IRenderer.hh:517
virtual void copyDepthToBackBuffer(GLuint _depthTex, float _scale=1.0f)
Copy texture to depth buffer.
Definition: IRenderer.cc:1337
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects)
Definition: IRenderer.cc:1201
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:1129
virtual void finishRenderingPipeline(bool _drawOverlay=true)
Draw overlay objects and reset OpenGL state.
Definition: IRenderer.cc:667
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:532
std::vector< ACG::RenderObject > renderObjects_
array of renderobjects, filled by addRenderObject()
Definition: IRenderer.hh:509
int numLights_
Number of Lights.
Definition: IRenderer.hh:499
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:1272
virtual void restoreInputFbo()
Restore the previously saved input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:783
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:138
void addOutput(const QString &_output)
Add one GLSL output specifier.
void addUniform(QString _uniform, QString _comment="")
Add one GLSL uniform specifier.
static void setShaderDir(QString _dir)
GLSL::Program * peelBlend_
blends one depth-layer into the current scene target
int peelMode_
mode: 0 -> front to back peeling, 1 -> dual peeling
int maxPeelCount_
max peel count
std::map< int, ViewerResources > viewerRes_
void initDepthPeeling()
Allocate framebuffers and load shaders for depth-peeling.
GLSL::Program * peelFinal_
final copy into back-buffer
void renderFrontPeeling(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
peel the scene from front to back, one layer per pass
GLuint peelQueryID_
occlusion query determining end of peeling (last layer)
void addRenderObject(ACG::RenderObject *_renderObject)
overide addRenderObject function to include OIT check
void initDualDepthPeeling()
Allocate framebuffers and load shaders for dual-depth-peeling.
QString renderObjectsInfo(bool _outputShaderInfo)
Return a qstring of the current render objects.
GLSL::Program * peelBlendDual_
dual depth peeling shaders
void renderDualPeeling(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
peel the scene with dual depth peeling, two layers per pass
GLSL program class.
Definition: GLSLShader.hh:211
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
Definition: GLSLShader.cc:724
void disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:355
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:326
void use()
Enables the program object for using.
Definition: GLSLShader.cc:345
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:385
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
Definition: GLSLShader.cc:692
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
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:95
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
Definition: DepthPeeling.cc:67
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
Definition: DepthPeeling.cc:81
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
Definition: DepthPeeling.cc:74
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
ACG::Vec4f backgroundColor()
Get current background color.
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
Namespace providing different geometric functions concerning angles.
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129
void glCheckErrors()
Definition: GLError.hh:96
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
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:99
ShaderGenDesc shaderDesc
Drawmode and other shader params.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
unsigned int internalFlags_
may be used internally by the renderer
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
Collection of framebuffers for each viewport.
unsigned int height_
viewer window height
unsigned int width_
viewer window width