1 /*=========================================================================
2 
3 Program:   Visualization Toolkit
4 Module:    vtkDepthPeelingPass.cxx
5 
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #include "vtkDepthPeelingPass.h"
17 #include "vtkOpenGLFramebufferObject.h"
18 #include "vtkInformation.h"
19 #include "vtkObjectFactory.h"
20 #include "vtkOpenGLActor.h"
21 #include "vtkOpenGLError.h"
22 #include "vtkOpenGLQuadHelper.h"
23 #include "vtkOpenGLRenderWindow.h"
24 #include "vtkOpenGLRenderer.h"
25 #include "vtkOpenGLShaderCache.h"
26 #include "vtkOpenGLState.h"
27 #include "vtkProp.h"
28 #include "vtkRenderState.h"
29 #include "vtkRenderer.h"
30 #include "vtkShaderProgram.h"
31 #include "vtkTextureObject.h"
32 #include <cassert>
33 #include <list>
34 
35 #include "vtkRenderStepsPass.h"
36 
37 #include "vtkOpenGLHelper.h"
38 
39 // the 2D blending shaders we use
40 #include "vtkDepthPeelingPassIntermediateFS.h"
41 #include "vtkDepthPeelingPassFinalFS.h"
42 
43 vtkStandardNewMacro(vtkDepthPeelingPass);
44 vtkCxxSetObjectMacro(vtkDepthPeelingPass,TranslucentPass,vtkRenderPass);
45 
46 // ----------------------------------------------------------------------------
vtkDepthPeelingPass()47 vtkDepthPeelingPass::vtkDepthPeelingPass() :
48   Framebuffer(nullptr)
49 {
50   this->TranslucentPass=nullptr;
51 
52   this->OcclusionRatio=0.0;
53   this->MaximumNumberOfPeels=4;
54 
55   this->IntermediateBlend = nullptr;
56   this->FinalBlend = nullptr;
57 
58   this->OpaqueRGBATexture = nullptr;
59   this->OpaqueZTexture = nullptr;
60   this->OwnOpaqueZTexture = false;
61   this->OwnOpaqueRGBATexture = false;
62 
63   this->TranslucentZTexture[0] = vtkTextureObject::New();
64   this->TranslucentZTexture[1] = vtkTextureObject::New();
65   this->DepthFormat = vtkTextureObject::Float32;
66 
67   for (int i = 0; i < 3; i++)
68   {
69     this->TranslucentRGBATexture[i] = vtkTextureObject::New();
70   }
71 
72   this->ViewportX = 0;
73   this->ViewportY = 0;
74   this->ViewportWidth = 100;
75   this->ViewportHeight = 100;
76 }
77 
78 // ----------------------------------------------------------------------------
~vtkDepthPeelingPass()79 vtkDepthPeelingPass::~vtkDepthPeelingPass()
80 {
81   if(this->TranslucentPass!=nullptr)
82   {
83     this->TranslucentPass->Delete();
84   }
85   if (this->OpaqueZTexture)
86   {
87     this->OpaqueZTexture->UnRegister(this);
88     this->OpaqueZTexture = nullptr;
89   }
90   if (this->TranslucentZTexture[0])
91   {
92     this->TranslucentZTexture[0]->UnRegister(this);
93     this->TranslucentZTexture[0] = nullptr;
94   }
95   if (this->TranslucentZTexture[1])
96   {
97     this->TranslucentZTexture[1]->UnRegister(this);
98     this->TranslucentZTexture[1] = nullptr;
99   }
100   if (this->OpaqueRGBATexture)
101   {
102     this->OpaqueRGBATexture->UnRegister(this);
103     this->OpaqueRGBATexture = nullptr;
104   }
105   for (int i = 0; i < 3; i++)
106   {
107     if (this->TranslucentRGBATexture[i])
108     {
109       this->TranslucentRGBATexture[i]->UnRegister(this);
110       this->TranslucentRGBATexture[i] = nullptr;
111     }
112   }
113   if (this->Framebuffer)
114   {
115     this->Framebuffer->UnRegister(this);
116     this->Framebuffer = nullptr;
117   }
118 }
119 
120 //-----------------------------------------------------------------------------
121 // Description:
122 // Destructor. Delete SourceCode if any.
ReleaseGraphicsResources(vtkWindow * w)123 void vtkDepthPeelingPass::ReleaseGraphicsResources(vtkWindow *w)
124 {
125   assert("pre: w_exists" && w!=nullptr);
126 
127   if (this->FinalBlend !=nullptr)
128   {
129     delete this->FinalBlend;
130     this->FinalBlend = nullptr;
131   }
132   if (this->IntermediateBlend !=nullptr)
133   {
134     delete this->IntermediateBlend;
135     this->IntermediateBlend = nullptr;
136   }
137   if(this->TranslucentPass)
138   {
139     this->TranslucentPass->ReleaseGraphicsResources(w);
140   }
141   if (this->OpaqueZTexture)
142   {
143     this->OpaqueZTexture->ReleaseGraphicsResources(w);
144   }
145   if (this->TranslucentZTexture[0])
146   {
147     this->TranslucentZTexture[0]->ReleaseGraphicsResources(w);
148   }
149   if (this->TranslucentZTexture[1])
150   {
151     this->TranslucentZTexture[1]->ReleaseGraphicsResources(w);
152   }
153   if (this->OpaqueRGBATexture)
154   {
155     this->OpaqueRGBATexture->ReleaseGraphicsResources(w);
156   }
157   for (int i = 0; i < 3; i++)
158   {
159     if (this->TranslucentRGBATexture[i])
160     {
161       this->TranslucentRGBATexture[i]->ReleaseGraphicsResources(w);
162     }
163   }
164   if (this->Framebuffer)
165   {
166     this->Framebuffer->ReleaseGraphicsResources(w);
167     this->Framebuffer->UnRegister(this);
168     this->Framebuffer = nullptr;
169   }
170 
171 }
172 
SetOpaqueZTexture(vtkTextureObject * to)173 void vtkDepthPeelingPass::SetOpaqueZTexture(vtkTextureObject *to)
174 {
175   if (this->OpaqueZTexture == to)
176   {
177     return;
178   }
179   if (this->OpaqueZTexture)
180   {
181     this->OpaqueZTexture->Delete();
182   }
183   this->OpaqueZTexture = to;
184   if (to)
185   {
186     to->Register(this);
187   }
188   this->OwnOpaqueZTexture = false;
189   this->Modified();
190 }
191 
SetOpaqueRGBATexture(vtkTextureObject * to)192 void vtkDepthPeelingPass::SetOpaqueRGBATexture(vtkTextureObject *to)
193 {
194   if (this->OpaqueRGBATexture == to)
195   {
196     return;
197   }
198   if (this->OpaqueRGBATexture)
199   {
200     this->OpaqueRGBATexture->Delete();
201   }
202   this->OpaqueRGBATexture = to;
203   if (to)
204   {
205     to->Register(this);
206   }
207   this->OwnOpaqueRGBATexture = false;
208   this->Modified();
209 }
210 
211 // ----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)212 void vtkDepthPeelingPass::PrintSelf(ostream& os, vtkIndent indent)
213 {
214   this->Superclass::PrintSelf(os,indent);
215 
216   os << indent << "OcclusionRatio: " << this->OcclusionRatio << endl;
217 
218   os << indent << "MaximumNumberOfPeels: " << this->MaximumNumberOfPeels
219      << endl;
220 
221   os << indent << "TranslucentPass:";
222   if(this->TranslucentPass!=nullptr)
223   {
224     this->TranslucentPass->PrintSelf(os,indent);
225   }
226   else
227   {
228     os << "(none)" <<endl;
229   }
230 }
231 
vtkDepthPeelingPassCreateTexture(vtkTextureObject * to,vtkOpenGLRenderWindow * context,int width,int height,int numComponents,bool isDepth,int depthFormat)232 void vtkDepthPeelingPassCreateTexture(
233   vtkTextureObject *to,
234   vtkOpenGLRenderWindow *context, int width, int height,
235   int numComponents, bool isDepth, int depthFormat)
236 {
237   to->SetContext(context);
238   if (isDepth == true)
239   {
240     to->AllocateDepth(width, height, depthFormat);
241   }
242   else
243   {
244     to->Allocate2D(width, height, numComponents, VTK_UNSIGNED_CHAR);
245   }
246 
247   to->SetMinificationFilter(vtkTextureObject::Nearest);
248   to->SetMagnificationFilter(vtkTextureObject::Nearest);
249   to->SetWrapS(vtkTextureObject::ClampToEdge);
250   to->SetWrapT(vtkTextureObject::ClampToEdge);
251 }
252 
BlendIntermediatePeels(vtkOpenGLRenderWindow * renWin,bool done)253 void vtkDepthPeelingPass::BlendIntermediatePeels(
254   vtkOpenGLRenderWindow *renWin,
255   bool done)
256 {
257   // take the TranslucentRGBA texture and blend it with the current frame buffer
258   if (!this->IntermediateBlend)
259   {
260     this->IntermediateBlend = new vtkOpenGLQuadHelper(renWin,
261       nullptr,
262       vtkDepthPeelingPassIntermediateFS,
263       "");
264   }
265   else
266   {
267     renWin->GetShaderCache()->ReadyShaderProgram(
268       this->IntermediateBlend->Program);
269   }
270   this->IntermediateBlend->Program->SetUniformi(
271     "translucentRGBATexture",
272     this->TranslucentRGBATexture[(this->ColorDrawCount - 2) % 3]->GetTextureUnit());
273   this->IntermediateBlend->Program->SetUniformi(
274     "currentRGBATexture",
275     this->TranslucentRGBATexture[(this->ColorDrawCount - 1) % 3]->GetTextureUnit());
276   this->IntermediateBlend->Program->SetUniformi(
277     "lastpass", done ? 1 : 0);
278 
279   this->State->vtkglDisable(GL_DEPTH_TEST);
280 
281   this->Framebuffer->AddColorAttachment(
282     this->Framebuffer->GetBothMode(), 0,
283     this->TranslucentRGBATexture[this->ColorDrawCount % 3]);
284   this->ColorDrawCount++;
285 
286   this->IntermediateBlend->Render();
287 }
288 
BlendFinalPeel(vtkOpenGLRenderWindow * renWin)289 void vtkDepthPeelingPass::BlendFinalPeel(vtkOpenGLRenderWindow *renWin)
290 {
291   if (!this->FinalBlend)
292   {
293     this->FinalBlend = new vtkOpenGLQuadHelper(renWin,
294       nullptr,
295       vtkDepthPeelingPassFinalFS,
296       "");
297   }
298   else
299   {
300     renWin->GetShaderCache()->ReadyShaderProgram(
301       this->FinalBlend->Program);
302   }
303 
304   if (this->FinalBlend->Program)
305   {
306     this->FinalBlend->Program->SetUniformi(
307       "translucentRGBATexture",
308       this->TranslucentRGBATexture[(this->ColorDrawCount - 1) % 3]->GetTextureUnit());
309 
310     this->OpaqueRGBATexture->Activate();
311     this->FinalBlend->Program->SetUniformi(
312       "opaqueRGBATexture", this->OpaqueRGBATexture->GetTextureUnit());
313 
314     this->OpaqueZTexture->Activate();
315     this->FinalBlend->Program->SetUniformi(
316       "opaqueZTexture", this->OpaqueZTexture->GetTextureUnit());
317 
318     this->Framebuffer->AddColorAttachment(
319       this->Framebuffer->GetBothMode(), 0,
320       this->TranslucentRGBATexture[this->ColorDrawCount % 3]);
321     this->ColorDrawCount++;
322 
323     // blend in OpaqueRGBA
324     this->State->vtkglEnable(GL_DEPTH_TEST);
325     this->State->vtkglDepthFunc( GL_ALWAYS );
326 
327     // do we need to set the viewport
328     this->FinalBlend->Render();
329   }
330   this->State->vtkglDepthFunc( GL_LEQUAL );
331 }
332 
333 
334 // ----------------------------------------------------------------------------
335 // Description:
336 // Perform rendering according to a render state \p s.
337 // \pre s_exists: s!=0
Render(const vtkRenderState * s)338 void vtkDepthPeelingPass::Render(const vtkRenderState *s)
339 {
340   assert("pre: s_exists" && s!=nullptr);
341 
342   this->NumberOfRenderedProps=0;
343 
344   if(this->TranslucentPass==nullptr)
345   {
346     vtkWarningMacro(<<"No TranslucentPass delegate set. Nothing can be rendered.");
347     return;
348   }
349 
350   // Any prop to render?
351   bool hasTranslucentPolygonalGeometry=false;
352   int i=0;
353   while(!hasTranslucentPolygonalGeometry && i<s->GetPropArrayCount())
354   {
355     hasTranslucentPolygonalGeometry=
356       s->GetPropArray()[i]->HasTranslucentPolygonalGeometry()==1;
357     ++i;
358   }
359   if(!hasTranslucentPolygonalGeometry)
360   {
361     return; // nothing to render.
362   }
363 
364   // check driver support
365   vtkOpenGLRenderWindow *renWin
366     = vtkOpenGLRenderWindow::SafeDownCast(s->GetRenderer()->GetRenderWindow());
367   this->State = renWin->GetState();
368 
369   // we need alpha planes
370   int rgba[4];
371   renWin->GetColorBufferSizes(rgba);
372 
373   if (rgba[3] < 8)
374   {
375     // just use alpha blending
376     this->TranslucentPass->Render(s);
377     return;
378   }
379 
380   // Depth peeling.
381   vtkRenderer *r=s->GetRenderer();
382 
383   if(s->GetFrameBuffer()==nullptr)
384   {
385     // get the viewport dimensions
386     r->GetTiledSizeAndOrigin(&this->ViewportWidth,&this->ViewportHeight,
387                              &this->ViewportX,&this->ViewportY);
388   }
389   else
390   {
391     int size[2];
392     s->GetWindowSize(size);
393     this->ViewportWidth=size[0];
394     this->ViewportHeight=size[1];
395     this->ViewportX=0;
396     this->ViewportY=0;
397   }
398 
399   // create textures we need if not done already
400   if (this->TranslucentRGBATexture[0]->GetHandle() == 0)
401   {
402     for (i = 0; i < 3; i++)
403     {
404       vtkDepthPeelingPassCreateTexture(
405         this->TranslucentRGBATexture[i],
406         renWin, this->ViewportWidth, this->ViewportHeight,
407         4, false, 0);
408     }
409     vtkDepthPeelingPassCreateTexture(
410       this->TranslucentZTexture[0],
411       renWin, this->ViewportWidth, this->ViewportHeight, 1, true, this->DepthFormat);
412     vtkDepthPeelingPassCreateTexture(
413       this->TranslucentZTexture[1],
414       renWin, this->ViewportWidth, this->ViewportHeight, 1, true, this->DepthFormat);
415     if (!this->OpaqueZTexture)
416     {
417       this->OwnOpaqueZTexture = true;
418       this->OpaqueZTexture = vtkTextureObject::New();
419       vtkDepthPeelingPassCreateTexture(
420         this->OpaqueZTexture,
421         renWin, this->ViewportWidth, this->ViewportHeight, 1, true, this->DepthFormat);
422     }
423     if (!this->OpaqueRGBATexture)
424     {
425       this->OwnOpaqueRGBATexture = true;
426       this->OpaqueRGBATexture = vtkTextureObject::New();
427       vtkDepthPeelingPassCreateTexture(
428       this->OpaqueRGBATexture,
429         renWin, this->ViewportWidth, this->ViewportHeight,
430         4, false, 0);
431     }
432   }
433 
434   for (i = 0; i < 3; i++)
435   {
436     this->TranslucentRGBATexture[i]->Resize(
437       this->ViewportWidth, this->ViewportHeight);
438   }
439   this->TranslucentZTexture[0]->Resize(
440     this->ViewportWidth, this->ViewportHeight);
441   this->TranslucentZTexture[1]->Resize(
442     this->ViewportWidth, this->ViewportHeight);
443 
444   if (this->OwnOpaqueZTexture)
445   {
446     this->OpaqueZTexture->Resize(
447       this->ViewportWidth, this->ViewportHeight);
448     this->OpaqueZTexture->CopyFromFrameBuffer(this->ViewportX, this->ViewportY,
449       this->ViewportX, this->ViewportY,
450       this->ViewportWidth, this->ViewportHeight);
451   }
452 
453   if (this->OwnOpaqueRGBATexture)
454   {
455     this->OpaqueRGBATexture->Resize(
456       this->ViewportWidth, this->ViewportHeight);
457     this->OpaqueRGBATexture->CopyFromFrameBuffer(this->ViewportX, this->ViewportY,
458       this->ViewportX, this->ViewportY,
459       this->ViewportWidth, this->ViewportHeight);
460   }
461 
462   if (!this->Framebuffer)
463   {
464     this->Framebuffer = vtkOpenGLFramebufferObject::New();
465     this->Framebuffer->SetContext(renWin);
466   }
467   this->Framebuffer->SaveCurrentBindingsAndBuffers();
468   this->Framebuffer->Bind();
469   this->Framebuffer->AddDepthAttachment(
470     this->Framebuffer->GetBothMode(), this->TranslucentZTexture[0]);
471   this->Framebuffer->AddColorAttachment(
472     this->Framebuffer->GetBothMode(), 0,
473     this->TranslucentRGBATexture[0]);
474 
475   this->State->vtkglViewport(0, 0,
476              this->ViewportWidth, this->ViewportHeight);
477   bool saveScissorTestState = this->State->GetEnumState(GL_SCISSOR_TEST);
478   this->State->vtkglDisable(GL_SCISSOR_TEST);
479 
480   this->State->vtkglClearDepth(static_cast<GLclampf>(0.0));
481   this->State->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
482 
483   this->State->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
484   this->State->vtkglClearColor(0.0,0.0,0.0,0.0); // always clear to black
485   this->State->vtkglClearDepth(static_cast<GLclampf>(1.0));
486   // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
487 
488   this->Framebuffer->AddDepthAttachment(
489     this->Framebuffer->GetBothMode(),
490     this->TranslucentZTexture[1]);
491   this->State->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
492 
493 #ifdef GL_MULTISAMPLE
494   bool multiSampleStatus = this->State->GetEnumState(GL_MULTISAMPLE);
495   this->State->vtkglDisable(GL_MULTISAMPLE);
496 #endif
497   this->State->vtkglDisable(GL_BLEND);
498 
499   this->TranslucentZTexture[0]->Activate();
500   this->OpaqueZTexture->Activate();
501 
502   this->TranslucentRGBATexture[0]->Activate();
503   this->TranslucentRGBATexture[1]->Activate();
504   this->TranslucentRGBATexture[2]->Activate();
505 
506   // Setup property keys for actors:
507   this->PreRender(s);
508 
509   // Enable the depth buffer (otherwise it's disabled for translucent geometry)
510   assert("Render state valid." && s);
511   int numProps = s->GetPropArrayCount();
512   for (int j = 0; j < numProps; ++j)
513   {
514     vtkProp *prop = s->GetPropArray()[j];
515     vtkInformation *info = prop->GetPropertyKeys();
516     if (!info)
517     {
518       info = vtkInformation::New();
519       prop->SetPropertyKeys(info);
520       info->FastDelete();
521     }
522     info->Set(vtkOpenGLActor::GLDepthMaskOverride(), 1);
523   }
524 
525   // Do render loop until complete
526   unsigned int threshold=
527     static_cast<unsigned int>(
528       this->ViewportWidth*this->ViewportHeight*OcclusionRatio);
529 
530 #if GL_ES_VERSION_3_0 != 1
531   GLuint queryId;
532   glGenQueries(1,&queryId);
533 #endif
534 
535   bool done = false;
536   GLuint nbPixels = threshold + 1;
537   this->PeelCount = 0;
538   this->ColorDrawCount = 0;
539   this->State->vtkglDepthFunc( GL_LEQUAL );
540   while(!done)
541   {
542     this->State->vtkglDepthMask(GL_TRUE);
543     this->State->vtkglEnable(GL_DEPTH_TEST);
544 
545     this->Framebuffer->AddColorAttachment(
546       this->Framebuffer->GetBothMode(), 0,
547       this->TranslucentRGBATexture[this->ColorDrawCount % 3]);
548     this->ColorDrawCount++;
549 
550     // clear the zbuffer and color buffers
551     this->State->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
552 
553     // render the translucent geometry
554 #if GL_ES_VERSION_3_0 != 1
555     glBeginQuery(GL_SAMPLES_PASSED,queryId);
556 #endif
557 
558     // check if we are going to exceed the max number of peels or if we
559     // exceeded the pixel threshold last time
560     this->PeelCount++;
561     if ((this->MaximumNumberOfPeels && this->PeelCount >= this->MaximumNumberOfPeels) ||
562        nbPixels <= threshold)
563     {
564       done = true;
565       // if so we do this last render using alpha blending for all
566       // the stuff that is left
567       this->State->vtkglEnable(GL_BLEND);
568       this->State->vtkglDepthFunc( GL_ALWAYS );
569     }
570     this->TranslucentPass->Render(s);
571     this->State->vtkglDepthFunc( GL_LEQUAL );
572     this->State->vtkglDisable(GL_BLEND);
573 
574 #if GL_ES_VERSION_3_0 != 1
575     glEndQuery(GL_SAMPLES_PASSED);
576     glGetQueryObjectuiv(queryId,GL_QUERY_RESULT,&nbPixels);
577 #endif
578     // cerr << "Pass " << peelCount << " pixels Drawn " << nbPixels << "\n";
579 
580     // if something was drawn, blend it in
581     if (nbPixels > 0)
582     {
583       // update translucentZ pingpong the textures
584       if (this->PeelCount % 2)
585       {
586         this->TranslucentZTexture[0]->Deactivate();
587         this->Framebuffer->AddDepthAttachment(
588           this->Framebuffer->GetBothMode(), this->TranslucentZTexture[0]);
589         this->TranslucentZTexture[1]->Activate();
590       }
591       else
592       {
593         this->TranslucentZTexture[1]->Deactivate();
594         this->Framebuffer->AddDepthAttachment(
595           this->Framebuffer->GetBothMode(), this->TranslucentZTexture[1]);
596         this->TranslucentZTexture[0]->Activate();
597       }
598 
599       // blend the last two peels together
600       if (this->PeelCount > 1)
601       {
602         this->BlendIntermediatePeels(renWin,done);
603       }
604     }
605     else // if we drew nothing we are done
606     {
607       this->ColorDrawCount--;
608       done = true;
609     }
610   }
611 
612 //  std::cout << "Number of peels: " << peelCount << "\n";
613 
614   // do the final blend if anything was drawn
615   // something is drawn only when ColorDrawCount
616   // is not zero or PeelCount is > 1
617   if (this->PeelCount > 1 || this->ColorDrawCount != 0)
618   {
619     this->BlendFinalPeel(renWin);
620   }
621 
622   this->Framebuffer->RestorePreviousBindingsAndBuffers();
623 
624 
625   // Restore the original viewport and scissor test settings
626   this->State->vtkglViewport(this->ViewportX, this->ViewportY,
627              this->ViewportWidth, this->ViewportHeight);
628   if (saveScissorTestState)
629   {
630     this->State->vtkglEnable(GL_SCISSOR_TEST);
631   }
632   else
633   {
634     this->State->vtkglDisable(GL_SCISSOR_TEST);
635   }
636 
637   //blit if we drew something
638   if (this->PeelCount > 1 || this->ColorDrawCount != 0)
639   {
640     this->Framebuffer->SaveCurrentBindingsAndBuffers(
641       this->Framebuffer->GetReadMode());
642     this->Framebuffer->Bind(
643       this->Framebuffer->GetReadMode());
644 
645     glBlitFramebuffer(
646       0, 0,
647       this->ViewportWidth, this->ViewportHeight,
648       this->ViewportX, this->ViewportY,
649       this->ViewportX + this->ViewportWidth,
650       this->ViewportY + this->ViewportHeight,
651       GL_COLOR_BUFFER_BIT,
652       GL_LINEAR);
653 
654     this->Framebuffer->RestorePreviousBindingsAndBuffers(
655       this->Framebuffer->GetReadMode());
656   }
657 
658 #ifdef GL_MULTISAMPLE
659    if(multiSampleStatus)
660    {
661       this->State->vtkglEnable(GL_MULTISAMPLE);
662    }
663 #endif
664 
665   // unload the textures
666   this->OpaqueZTexture->Deactivate();
667   this->OpaqueRGBATexture->Deactivate();
668   this->TranslucentRGBATexture[0]->Deactivate();
669   this->TranslucentRGBATexture[1]->Deactivate();
670   this->TranslucentRGBATexture[2]->Deactivate();
671   this->TranslucentZTexture[0]->Deactivate();
672   this->TranslucentZTexture[1]->Deactivate();
673 
674   // restore blending
675   this->State->vtkglEnable(GL_BLEND);
676 
677   this->PostRender(s);
678   for (int j = 0; j < numProps; ++j)
679   {
680     vtkProp *prop = s->GetPropArray()[j];
681     vtkInformation *info = prop->GetPropertyKeys();
682     if (info)
683     {
684       info->Remove(vtkOpenGLActor::GLDepthMaskOverride());
685     }
686   }
687 
688   this->NumberOfRenderedProps = this->TranslucentPass->GetNumberOfRenderedProps();
689 
690   vtkOpenGLCheckErrorMacro("failed after Render");
691 }
692 
693 //------------------------------------------------------------------------------
PostReplaceShaderValues(std::string &,std::string &,std::string & fragmentShader,vtkAbstractMapper *,vtkProp *)694 bool vtkDepthPeelingPass::PostReplaceShaderValues(std::string &,
695                                               std::string &,
696                                               std::string &fragmentShader,
697                                               vtkAbstractMapper *,
698                                               vtkProp *)
699 {
700   vtkShaderProgram::Substitute(
701         fragmentShader, "//VTK::DepthPeeling::Dec",
702         "uniform vec2 vpSize;\n"
703         "uniform sampler2D opaqueZTexture;\n"
704         "uniform sampler2D translucentZTexture;\n"
705         );
706 
707   // Set gl_FragDepth if it isn't set already. It may have already been replaced
708   // by the mapper, in which case the substitution will fail and the previously
709   // set depth value will be used.
710   vtkShaderProgram::Substitute(
711         fragmentShader, "//VTK::Depth::Impl",
712         "gl_FragDepth = gl_FragCoord.z;");
713 
714   // the .0000001 below is an epsilon.  It turns out that
715   // graphics cards can render the same polygon two times
716   // in a row with different z values. I suspect it has to
717   // do with how rasterization of the polygon is broken up.
718   // A different breakup across fragment shaders can result in
719   // very slightly different z values for some of the pixels.
720   // The end result is that with depth peeling, you can end up
721   // counting/accumulating pixels of the same surface twice
722   // simply due to this randomness in z values. So we introduce
723   // an epsilon into the transparent test to require some
724   // minimal z separation between pixels
725   vtkShaderProgram::Substitute(
726         fragmentShader, "//VTK::DepthPeeling::Impl",
727         "vec2 dpTexCoord = gl_FragCoord.xy / vpSize;\n"
728         "  float odepth = texture2D(opaqueZTexture, dpTexCoord).r;\n"
729         "  if (gl_FragDepth >= odepth) { discard; }\n"
730         "  float tdepth = texture2D(translucentZTexture, dpTexCoord).r;\n"
731         "  if (gl_FragDepth <= tdepth + .0000001) { discard; }\n"
732         );
733 
734   return true;
735 }
736 
737 //------------------------------------------------------------------------------
SetShaderParameters(vtkShaderProgram * program,vtkAbstractMapper *,vtkProp *,vtkOpenGLVertexArrayObject * vtkNotUsed (VAO))738 bool vtkDepthPeelingPass::SetShaderParameters(vtkShaderProgram *program,
739                                    vtkAbstractMapper*, vtkProp*,
740                                    vtkOpenGLVertexArrayObject* vtkNotUsed(VAO))
741 {
742   program->SetUniformi("opaqueZTexture",
743                        this->OpaqueZTexture->GetTextureUnit());
744   program->SetUniformi("translucentZTexture",
745                        this->TranslucentZTexture[(this->PeelCount + 1) % 2]->GetTextureUnit());
746 
747   float vpSize[2] = { static_cast<float>(this->ViewportWidth),
748                       static_cast<float>(this->ViewportHeight) };
749   program->SetUniform2f("vpSize", vpSize);
750 
751   return true;
752 }
753