Developer Documentation
Loading...
Searching...
No Matches
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
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
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.
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects)
virtual void renderObject(ACG::RenderObject *_obj, GLSL::Program *_prog=0, bool _constRenderStates=false, const std::vector< unsigned int > *_shaderModifiers=0)
Render one renderobject.
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.
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.
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
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)
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
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.
int getFragDataLocation(const char *_name)
Get location of the fragment data output.
void disable()
Resets to standard rendering pipeline.
void link()
Links the shader objects to the program.
void use()
Enables the program object for using.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
void bindFragDataLocation(unsigned int _index, const char *_name)
Bind fragment output data to name.
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.
void modifyFragmentIO(ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
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)
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
Interface class between scenegraph and renderer.
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