1 /*=========================================================================
2 
3 Program:   Visualization Toolkit
4 Module:    vtkOpenGLRenderer.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 #include "vtkOpenGLRenderer.h"
16 
17 #include "vtkOpenGLHelper.h"
18 
19 #include "vtkCellArray.h"
20 #include "vtkDepthPeelingPass.h"
21 #include "vtkDualDepthPeelingPass.h"
22 #include "vtkFloatArray.h"
23 #include "vtkHardwareSelector.h"
24 #include "vtkHiddenLineRemovalPass.h"
25 #include "vtkLight.h"
26 #include "vtkLightCollection.h"
27 #include "vtkNew.h"
28 #include "vtkObjectFactory.h"
29 #include "vtkOpenGLCamera.h"
30 #include "vtkOpenGLError.h"
31 #include "vtkOpenGLFXAAFilter.h"
32 #include "vtkOpenGLRenderWindow.h"
33 #include "vtkOpenGLState.h"
34 #include "vtkOrderIndependentTranslucentPass.h"
35 #include "vtkPointData.h"
36 #include "vtkPoints.h"
37 #include "vtkPolyData.h"
38 #include "vtkPolyDataMapper2D.h"
39 #include "vtkRenderPass.h"
40 #include "vtkRenderState.h"
41 #include "vtkRenderTimerLog.h"
42 #include "vtkShaderProgram.h"
43 #include "vtkShadowMapBakerPass.h"
44 #include "vtkShadowMapPass.h"
45 #include "vtkTexture.h"
46 #include "vtkTextureObject.h"
47 #include "vtkTexturedActor2D.h"
48 #include "vtkTimerLog.h"
49 #include "vtkTransform.h"
50 #include "vtkTranslucentPass.h"
51 #include "vtkTrivialProducer.h"
52 #include "vtkUnsignedCharArray.h"
53 #include "vtkVolumetricPass.h"
54 
55 #include <vtksys/RegularExpression.hxx>
56 
57 #include <cmath>
58 #include <cassert>
59 #include <cstdlib>
60 #include <list>
61 #include <sstream>
62 #include <string>
63 
64 #if defined(__APPLE__) && ! defined(VTK_OPENGL_HAS_OSMESA)
65 #include <CoreFoundation/CoreFoundation.h>
66 #endif
67 
68 vtkStandardNewMacro(vtkOpenGLRenderer);
69 
vtkOpenGLRenderer()70 vtkOpenGLRenderer::vtkOpenGLRenderer()
71 {
72   this->FXAAFilter = nullptr;
73   this->DepthPeelingPass = nullptr;
74   this->TranslucentPass = nullptr;
75   this->ShadowMapPass = nullptr;
76   this->DepthPeelingHigherLayer=0;
77 
78   this->HaveApplePrimitiveIdBugValue = false;
79   this->HaveApplePrimitiveIdBugChecked = false;
80 
81   this->LightingCount = -1;
82   this->LightingComplexity = -1;
83 }
84 
85 // Ask lights to load themselves into graphics pipeline.
UpdateLights()86 int vtkOpenGLRenderer::UpdateLights ()
87 {
88   // consider the lighting complexity to determine which case applies
89   // simple headlight, Light Kit, the whole feature set of VTK
90   vtkLightCollection *lc = this->GetLights();
91   vtkLight *light;
92 
93   int lightingComplexity = 0;
94   int lightingCount = 0;
95 
96   vtkMTimeType ltime = lc->GetMTime();
97 
98   vtkCollectionSimpleIterator sit;
99   for(lc->InitTraversal(sit);
100       (light = lc->GetNextLight(sit)); )
101   {
102     float status = light->GetSwitch();
103     if (status > 0.0)
104     {
105       ltime = vtkMath::Max(ltime, light->GetMTime());
106       lightingCount++;
107       if (lightingComplexity == 0)
108       {
109         lightingComplexity = 1;
110       }
111     }
112 
113     if (lightingComplexity == 1
114         && (lightingCount > 1
115           || light->GetLightType() != VTK_LIGHT_TYPE_HEADLIGHT))
116     {
117       lightingComplexity = 2;
118     }
119     if (lightingComplexity < 3
120         && (light->GetPositional()))
121     {
122       lightingComplexity = 3;
123     }
124   }
125 
126   // create alight if needed
127   if( !lightingCount )
128   {
129     if (this->AutomaticLightCreation)
130     {
131       vtkDebugMacro(<<"No lights are on, creating one.");
132       this->CreateLight();
133       lc->InitTraversal(sit);
134       light = lc->GetNextLight(sit);
135       ltime = lc->GetMTime();
136       lightingCount = 1;
137       lightingComplexity = light->GetLightType() == VTK_LIGHT_TYPE_HEADLIGHT ? 1 : 2;
138       ltime = vtkMath::Max(ltime, light->GetMTime());
139     }
140   }
141 
142   if (lightingComplexity != this->LightingComplexity ||
143       lightingCount != this->LightingCount)
144   {
145     this->LightingComplexity = lightingComplexity;
146     this->LightingCount = lightingCount;
147 
148     this->LightingUpdateTime = ltime;
149 
150     // rebuild the standard declarations
151     std::ostringstream toString;
152     switch (this->LightingComplexity)
153     {
154       case 0: // no lighting or RENDER_VALUES
155         this->LightingDeclaration = "";
156         break;
157 
158       case 1:  // headlight
159         this->LightingDeclaration = "uniform vec3 lightColor0;\n";
160         break;
161 
162       case 2: // light kit
163         toString.clear();
164         toString.str("");
165         for (int i = 0; i < this->LightingCount; ++i)
166         {
167           toString <<
168           "uniform vec3 lightColor" << i << ";\n"
169           "  uniform vec3 lightDirectionVC" << i << "; // normalized\n";
170         }
171         this->LightingDeclaration = toString.str();
172         break;
173 
174       case 3: // positional
175         toString.clear();
176         toString.str("");
177         for (int i = 0; i < this->LightingCount; ++i)
178         {
179           toString <<
180           "uniform vec3 lightColor" << i << ";\n"
181           "uniform vec3 lightDirectionVC" << i << "; // normalized\n"
182           "uniform vec3 lightPositionVC" << i << ";\n"
183           "uniform vec3 lightAttenuation" << i << ";\n"
184           "uniform float lightConeAngle" << i << ";\n"
185           "uniform float lightExponent" << i << ";\n"
186           "uniform int lightPositional" << i << ";";
187         }
188         this->LightingDeclaration = toString.str();
189         break;
190     }
191   }
192 
193   this->LightingUpdateTime = ltime;
194 
195   return this->LightingCount;
196 }
197 
198 // ----------------------------------------------------------------------------
199 // Description:
200 // Is rendering at translucent geometry stage using depth peeling and
201 // rendering a layer other than the first one? (Boolean value)
202 // If so, the uniform variables UseTexture and Texture can be set.
203 // (Used by vtkOpenGLProperty or vtkOpenGLTexture)
GetDepthPeelingHigherLayer()204 int vtkOpenGLRenderer::GetDepthPeelingHigherLayer()
205 {
206   return this->DepthPeelingHigherLayer;
207 }
208 
209 // ----------------------------------------------------------------------------
210 // Concrete open gl render method.
DeviceRender(void)211 void vtkOpenGLRenderer::DeviceRender(void)
212 {
213   vtkTimerLog::MarkStartEvent("OpenGL Dev Render");
214 
215   if(this->Pass!=nullptr)
216   {
217     vtkRenderState s(this);
218     s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
219     s.SetFrameBuffer(nullptr);
220     this->Pass->Render(&s);
221   }
222   else
223   {
224     // Do not remove this MakeCurrent! Due to Start / End methods on
225     // some objects which get executed during a pipeline update,
226     // other windows might get rendered since the last time
227     // a MakeCurrent was called.
228     this->RenderWindow->MakeCurrent();
229     vtkOpenGLClearErrorMacro();
230 
231     this->UpdateCamera();
232     this->UpdateLightGeometry();
233     this->UpdateLights();
234     this->UpdateGeometry();
235 
236     vtkOpenGLCheckErrorMacro("failed after DeviceRender");
237   }
238 
239   vtkTimerLog::MarkEndEvent("OpenGL Dev Render");
240 }
241 
242 // Ask actors to render themselves. As a side effect will cause
243 // visualization network to update.
UpdateGeometry()244 int vtkOpenGLRenderer::UpdateGeometry()
245 {
246   vtkRenderTimerLog *timer = this->GetRenderWindow()->GetRenderTimer();
247   VTK_SCOPED_RENDER_EVENT("vtkOpenGLRenderer::UpdateGeometry", timer);
248 
249   int        i;
250 
251   this->NumberOfPropsRendered = 0;
252 
253   if ( this->PropArrayCount == 0 )
254   {
255     return 0;
256   }
257 
258   if (this->Selector)
259   {
260     VTK_SCOPED_RENDER_EVENT2("Selection", timer, selectionEvent);
261 
262     // When selector is present, we are performing a selection,
263     // so do the selection rendering pass instead of the normal passes.
264     // Delegate the rendering of the props to the selector itself.
265 
266     // use pickfromprops ?
267     if (this->PickFromProps)
268     {
269       vtkProp **pa;
270       vtkProp *aProp;
271       if ( this->PickFromProps->GetNumberOfItems() > 0 )
272       {
273         pa = new vtkProp *[this->PickFromProps->GetNumberOfItems()];
274         int pac = 0;
275 
276         vtkCollectionSimpleIterator pit;
277         for ( this->PickFromProps->InitTraversal(pit);
278               (aProp = this->PickFromProps->GetNextProp(pit)); )
279         {
280           if ( aProp->GetVisibility() )
281           {
282             pa[pac++] = aProp;
283           }
284         }
285 
286         this->NumberOfPropsRendered = this->Selector->Render(this, pa, pac);
287         delete [] pa;
288       }
289     }
290     else
291     {
292       this->NumberOfPropsRendered = this->Selector->Render(this,
293         this->PropArray, this->PropArrayCount);
294     }
295 
296     this->RenderTime.Modified();
297     vtkDebugMacro("Rendered " << this->NumberOfPropsRendered << " actors" );
298     return this->NumberOfPropsRendered;
299   }
300 
301   // if we are suing shadows then let the renderpasses handle it
302   // for opaque and translucent
303   int hasTranslucentPolygonalGeometry = 0;
304   if (this->UseShadows)
305   {
306     VTK_SCOPED_RENDER_EVENT2("Shadows", timer, shadowsEvent);
307 
308     if (!this->ShadowMapPass)
309     {
310       this->ShadowMapPass = vtkShadowMapPass::New();
311     }
312     vtkRenderState s(this);
313     s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
314     //s.SetFrameBuffer(0);
315     this->ShadowMapPass->GetShadowMapBakerPass()->Render(&s);
316     this->ShadowMapPass->Render(&s);
317   }
318   else
319   {
320     // Opaque geometry first:
321     timer->MarkStartEvent("Opaque Geometry");
322     this->DeviceRenderOpaqueGeometry();
323     timer->MarkEndEvent();
324 
325     // do the render library specific stuff about translucent polygonal geometry.
326     // As it can be expensive, do a quick check if we can skip this step
327     for ( i = 0; !hasTranslucentPolygonalGeometry && i < this->PropArrayCount;
328           i++ )
329     {
330       hasTranslucentPolygonalGeometry=
331         this->PropArray[i]->HasTranslucentPolygonalGeometry();
332     }
333     if(hasTranslucentPolygonalGeometry)
334     {
335       timer->MarkStartEvent("Translucent Geometry");
336       this->DeviceRenderTranslucentPolygonalGeometry();
337       timer->MarkEndEvent();
338     }
339   }
340 
341   // Apply FXAA before volumes and overlays. Volumes don't need AA, and overlays
342   // are usually things like text, which are already antialiased.
343   if (this->UseFXAA)
344   {
345     timer->MarkStartEvent("FXAA");
346     if (!this->FXAAFilter)
347     {
348       this->FXAAFilter = vtkOpenGLFXAAFilter::New();
349     }
350     if (this->FXAAOptions)
351     {
352       this->FXAAFilter->UpdateConfiguration(this->FXAAOptions);
353     }
354 
355     this->FXAAFilter->Execute(this);
356     timer->MarkEndEvent();
357   }
358 
359   // loop through props and give them a chance to
360   // render themselves as volumetric geometry.
361   if (hasTranslucentPolygonalGeometry == 0 ||
362       !this->UseDepthPeeling ||
363       !this->UseDepthPeelingForVolumes)
364   {
365     timer->MarkStartEvent("Volumes");
366     for ( i = 0; i < this->PropArrayCount; i++ )
367     {
368       this->NumberOfPropsRendered +=
369         this->PropArray[i]->RenderVolumetricGeometry(this);
370     }
371     timer->MarkEndEvent();
372   }
373 
374   // loop through props and give them a chance to
375   // render themselves as an overlay (or underlay)
376   timer->MarkStartEvent("Overlay");
377   for ( i = 0; i < this->PropArrayCount; i++ )
378   {
379     this->NumberOfPropsRendered +=
380       this->PropArray[i]->RenderOverlay(this);
381   }
382   timer->MarkEndEvent();
383 
384   this->RenderTime.Modified();
385 
386   vtkDebugMacro( << "Rendered " <<
387                     this->NumberOfPropsRendered << " actors" );
388 
389   return  this->NumberOfPropsRendered;
390 }
391 
392 //----------------------------------------------------------------------------
GetCurrentTexturedBackground()393 vtkTexture* vtkOpenGLRenderer::GetCurrentTexturedBackground()
394 {
395   if (!this->GetRenderWindow()->GetStereoRender() && this->BackgroundTexture)
396   {
397     return this->BackgroundTexture;
398   }
399   else if (this->GetRenderWindow()->GetStereoRender() && this->GetActiveCamera()->GetLeftEye() == 1 && this->BackgroundTexture)
400   {
401     return this->BackgroundTexture;
402   }
403   else if (this->GetRenderWindow()->GetStereoRender() && this->RightBackgroundTexture)
404   {
405     return this->RightBackgroundTexture;
406   }
407   else
408   {
409     return nullptr;
410   }
411 }
412 
413 // ----------------------------------------------------------------------------
DeviceRenderOpaqueGeometry()414 void vtkOpenGLRenderer::DeviceRenderOpaqueGeometry()
415 {
416   // Do we need hidden line removal?
417   bool useHLR =
418       this->UseHiddenLineRemoval &&
419       vtkHiddenLineRemovalPass::WireframePropsExist(this->PropArray,
420                                                     this->PropArrayCount);
421 
422   if (useHLR)
423   {
424     vtkNew<vtkHiddenLineRemovalPass> hlrPass;
425     vtkRenderState s(this);
426     s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
427     s.SetFrameBuffer(nullptr);
428     hlrPass->Render(&s);
429     this->NumberOfPropsRendered += hlrPass->GetNumberOfRenderedProps();
430   }
431   else
432   {
433     this->Superclass::DeviceRenderOpaqueGeometry();
434   }
435 }
436 
437 // ----------------------------------------------------------------------------
438 // Description:
439 // Render translucent polygonal geometry. Default implementation just call
440 // UpdateTranslucentPolygonalGeometry().
441 // Subclasses of vtkRenderer that can deal with depth peeling must
442 // override this method.
DeviceRenderTranslucentPolygonalGeometry()443 void vtkOpenGLRenderer::DeviceRenderTranslucentPolygonalGeometry()
444 {
445   vtkOpenGLClearErrorMacro();
446 
447   vtkOpenGLRenderWindow *context
448     = vtkOpenGLRenderWindow::SafeDownCast(this->RenderWindow);
449 
450   if(this->UseDepthPeeling && !context)
451   {
452     vtkErrorMacro("OpenGL render window is required.")
453     return;
454   }
455 
456   if(!this->UseDepthPeeling)
457   {
458     // old code
459     // this->UpdateTranslucentPolygonalGeometry();
460 
461     // new approach
462     if (!this->TranslucentPass)
463     {
464       vtkOrderIndependentTranslucentPass *oit =
465         vtkOrderIndependentTranslucentPass::New();
466       this->TranslucentPass = oit;
467     }
468     vtkTranslucentPass *tp = vtkTranslucentPass::New();
469     this->TranslucentPass->SetTranslucentPass(tp);
470     tp->Delete();
471 
472     vtkRenderState s(this);
473     s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
474     s.SetFrameBuffer(nullptr);
475     this->LastRenderingUsedDepthPeeling=0;
476     this->TranslucentPass->Render(&s);
477     this->NumberOfPropsRendered += this->TranslucentPass->GetNumberOfRenderedProps();
478   }
479   else   // depth peeling.
480   {
481 #if GL_ES_VERSION_3_0 == 1
482     vtkErrorMacro("Built in Dual Depth Peeling is not supported on ES3. "
483       "Please see TestFramebufferPass.cxx for an example that should work "
484       "on OpenGL ES 3.");
485     this->UpdateTranslucentPolygonalGeometry();
486 #else
487     if (!this->DepthPeelingPass)
488     {
489       if (this->IsDualDepthPeelingSupported())
490       {
491         vtkDebugMacro("Using dual depth peeling.");
492         vtkDualDepthPeelingPass *ddpp = vtkDualDepthPeelingPass::New();
493         this->DepthPeelingPass = ddpp;
494       }
495       else
496       {
497         vtkDebugMacro("Using standard depth peeling (dual depth peeling not "
498                       "supported by the graphics card/driver).");
499         this->DepthPeelingPass = vtkDepthPeelingPass::New();
500       }
501       vtkTranslucentPass *tp = vtkTranslucentPass::New();
502       this->DepthPeelingPass->SetTranslucentPass(tp);
503       tp->Delete();
504     }
505 
506     if (this->UseDepthPeelingForVolumes)
507     {
508       vtkDualDepthPeelingPass *ddpp = vtkDualDepthPeelingPass::SafeDownCast(
509             this->DepthPeelingPass);
510       if (!ddpp)
511       {
512         vtkWarningMacro("UseDepthPeelingForVolumes requested, but unsupported "
513                         "since DualDepthPeeling is not available.");
514         this->UseDepthPeelingForVolumes = false;
515       }
516       else if (!ddpp->GetVolumetricPass())
517       {
518         vtkVolumetricPass *vp = vtkVolumetricPass::New();
519         ddpp->SetVolumetricPass(vp);
520         vp->Delete();
521       }
522     }
523     else
524     {
525       vtkDualDepthPeelingPass *ddpp = vtkDualDepthPeelingPass::SafeDownCast(
526             this->DepthPeelingPass);
527       if (ddpp)
528       {
529         ddpp->SetVolumetricPass(nullptr);
530       }
531     }
532 
533     this->DepthPeelingPass->SetMaximumNumberOfPeels(this->MaximumNumberOfPeels);
534     this->DepthPeelingPass->SetOcclusionRatio(this->OcclusionRatio);
535     vtkRenderState s(this);
536     s.SetPropArrayAndCount(this->PropArray, this->PropArrayCount);
537     s.SetFrameBuffer(nullptr);
538     this->LastRenderingUsedDepthPeeling=1;
539     this->DepthPeelingPass->Render(&s);
540     this->NumberOfPropsRendered += this->DepthPeelingPass->GetNumberOfRenderedProps();
541 #endif
542   }
543 
544   vtkOpenGLCheckErrorMacro("failed after DeviceRenderTranslucentPolygonalGeometry");
545 }
546 
547 
548 // ----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)549 void vtkOpenGLRenderer::PrintSelf(ostream& os, vtkIndent indent)
550 {
551   this->Superclass::PrintSelf(os,indent);
552 }
553 
554 
Clear(void)555 void vtkOpenGLRenderer::Clear(void)
556 {
557   vtkOpenGLClearErrorMacro();
558 
559   GLbitfield  clear_mask = 0;
560   vtkOpenGLState *ostate = this->GetState();
561 
562   if (! this->Transparent())
563   {
564     ostate->vtkglClearColor(static_cast<GLclampf>(this->Background[0]),
565       static_cast<GLclampf>(this->Background[1]), static_cast<GLclampf>(this->Background[2]),
566       static_cast<GLclampf>(this->BackgroundAlpha));
567     clear_mask |= GL_COLOR_BUFFER_BIT;
568   }
569 
570   if (!this->GetPreserveDepthBuffer())
571   {
572     ostate->vtkglClearDepth(static_cast<GLclampf>(1.0));
573     clear_mask |= GL_DEPTH_BUFFER_BIT;
574     ostate->vtkglDepthMask(GL_TRUE);
575   }
576 
577   vtkDebugMacro(<< "glClear\n");
578   ostate->vtkglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
579   ostate->vtkglClear(clear_mask);
580 
581   // If gradient background is turned on, draw it now.
582   if (!this->Transparent() &&
583       (this->GradientBackground || this->TexturedBackground))
584   {
585     int size[2];
586     size[0] = this->GetSize()[0];
587     size[1] = this->GetSize()[1];
588 
589     double tile_viewport[4];
590     this->GetRenderWindow()->GetTileViewport(tile_viewport);
591 
592     vtkNew<vtkTexturedActor2D> actor;
593     vtkNew<vtkPolyDataMapper2D> mapper;
594     vtkNew<vtkPolyData> polydata;
595     vtkNew<vtkPoints> points;
596     points->SetNumberOfPoints(4);
597     points->SetPoint(0, 0, 0, 0);
598     points->SetPoint(1, size[0], 0, 0);
599     points->SetPoint(2, size[0], size[1], 0);
600     points->SetPoint(3, 0, size[1], 0);
601     polydata->SetPoints(points);
602 
603     vtkNew<vtkCellArray> tris;
604     tris->InsertNextCell(3);
605     tris->InsertCellPoint(0);
606     tris->InsertCellPoint(1);
607     tris->InsertCellPoint(2);
608     tris->InsertNextCell(3);
609     tris->InsertCellPoint(0);
610     tris->InsertCellPoint(2);
611     tris->InsertCellPoint(3);
612     polydata->SetPolys(tris);
613 
614     vtkNew<vtkTrivialProducer> prod;
615     prod->SetOutput(polydata);
616 
617     // Set some properties.
618     mapper->SetInputConnection(prod->GetOutputPort());
619     actor->SetMapper(mapper);
620 
621     if(this->TexturedBackground && this->GetCurrentTexturedBackground())
622     {
623       this->GetCurrentTexturedBackground()->InterpolateOn();
624       actor->SetTexture(this->GetCurrentTexturedBackground());
625 
626       vtkNew<vtkFloatArray> tcoords;
627       float tmp[2];
628       tmp[0] = 0;
629       tmp[1] = 0;
630       tcoords->SetNumberOfComponents(2);
631       tcoords->SetNumberOfTuples(4);
632       tcoords->SetTuple(0,tmp);
633       tmp[0] = 1.0;
634       tcoords->SetTuple(1,tmp);
635       tmp[1] = 1.0;
636       tcoords->SetTuple(2,tmp);
637       tmp[0] = 0.0;
638       tcoords->SetTuple(3,tmp);
639       polydata->GetPointData()->SetTCoords(tcoords);
640     }
641     else // gradient
642     {
643       vtkNew<vtkUnsignedCharArray> colors;
644       float tmp[4];
645       tmp[0] = this->Background[0]*255;
646       tmp[1] = this->Background[1]*255;
647       tmp[2] = this->Background[2]*255;
648       tmp[3] = 255;
649       colors->SetNumberOfComponents(4);
650       colors->SetNumberOfTuples(4);
651       colors->SetTuple(0,tmp);
652       colors->SetTuple(1,tmp);
653       tmp[0] = this->Background2[0]*255;
654       tmp[1] = this->Background2[1]*255;
655       tmp[2] = this->Background2[2]*255;
656       colors->SetTuple(2,tmp);
657       colors->SetTuple(3,tmp);
658       polydata->GetPointData()->SetScalars(colors);
659     }
660 
661     ostate->vtkglDisable(GL_DEPTH_TEST);
662     actor->RenderOverlay(this);
663   }
664 
665   ostate->vtkglEnable(GL_DEPTH_TEST);
666 
667   vtkOpenGLCheckErrorMacro("failed after Clear");
668 }
669 
ReleaseGraphicsResources(vtkWindow * w)670 void vtkOpenGLRenderer::ReleaseGraphicsResources(vtkWindow *w)
671 {
672   if (w && this->Pass)
673   {
674     this->Pass->ReleaseGraphicsResources(w);
675   }
676   if (this->FXAAFilter)
677   {
678     this->FXAAFilter->ReleaseGraphicsResources();
679   }
680   if (w && this->DepthPeelingPass)
681   {
682     this->DepthPeelingPass->ReleaseGraphicsResources(w);
683   }
684   if (w && this->TranslucentPass)
685   {
686     this->TranslucentPass->ReleaseGraphicsResources(w);
687   }
688   if (w && this->ShadowMapPass)
689   {
690     this->ShadowMapPass->ReleaseGraphicsResources(w);
691   }
692   this->Superclass::ReleaseGraphicsResources(w);
693 }
694 
~vtkOpenGLRenderer()695 vtkOpenGLRenderer::~vtkOpenGLRenderer()
696 {
697   if(this->Pass != nullptr)
698   {
699     this->Pass->UnRegister(this);
700     this->Pass = nullptr;
701   }
702 
703   if (this->FXAAFilter)
704   {
705     this->FXAAFilter->Delete();
706     this->FXAAFilter = nullptr;
707   }
708 
709   if (this->ShadowMapPass)
710   {
711     this->ShadowMapPass->Delete();
712     this->ShadowMapPass = nullptr;
713   }
714 
715   if (this->DepthPeelingPass)
716   {
717     this->DepthPeelingPass->Delete();
718     this->DepthPeelingPass = nullptr;
719   }
720 
721   if (this->TranslucentPass)
722   {
723     this->TranslucentPass->Delete();
724     this->TranslucentPass = nullptr;
725   }
726 }
727 
HaveApplePrimitiveIdBug()728 bool vtkOpenGLRenderer::HaveApplePrimitiveIdBug()
729 {
730   if (this->HaveApplePrimitiveIdBugChecked)
731   {
732     return this->HaveApplePrimitiveIdBugValue;
733   }
734 
735 #if defined(__APPLE__) && ! defined(VTK_OPENGL_HAS_OSMESA)
736   // Known working Apple+AMD systems:
737   // OpenGL vendor string:  ATI Technologies Inc.
738   // OpenGL version string:   4.1 ATI-1.38.3
739   // OpenGL version string:   4.1 ATI-1.40.15
740   // OpenGL renderer string:    AMD Radeon R9 M370X OpenGL Engine
741 
742   // OpenGL version string:   4.1 ATI-1.40.16
743   // OpenGL renderer string:    AMD Radeon HD - FirePro D500 OpenGL Engine
744   // OpenGL renderer string:    AMD Radeon HD 5770 OpenGL Engine
745   // OpenGL renderer string:    AMD Radeon R9 M395 OpenGL Engine
746 
747   // OpenGL vendor string:  ATI Technologies Inc.
748   // OpenGL renderer string:  ATI Radeon HD 5770 OpenGL Engine
749   // OpenGL version string:  4.1 ATI-1.42.6
750 
751   // Known buggy Apple+AMD systems:
752   // OpenGL vendor string:  ATI Technologies Inc.
753   // OpenGL version string:   3.3 ATI-10.0.40
754   // OpenGL renderer string:    ATI Radeon HD 2600 PRO OpenGL Engine
755 
756   // OpenGL vendor string:  ATI Technologies Inc.
757   // OpenGL renderer string:  AMD Radeon HD - FirePro D300 OpenGL Engine
758   // OpenGL version string:  4.1 ATI-1.24.39
759 
760   std::string vendor = (const char *)glGetString(GL_VENDOR);
761   if (vendor.find("ATI") != std::string::npos ||
762       vendor.find("AMD") != std::string::npos ||
763       vendor.find("amd") != std::string::npos)
764   {
765     // assume we have the bug if we are running on <= macOS 10.10.x
766     // Apple fixed this bug in OS X 10.11 beta 15A216g.
767     // kCFCoreFoundationVersionNumber10_10_Max = 1199, we use the raw number
768     // because the constant isn't present in older SDKs.
769     if (kCFCoreFoundationVersionNumber <= 1199)
770     {
771       this->HaveApplePrimitiveIdBugValue = true;
772     }
773 
774     // but exclude systems we know do not have it
775     std::string renderer = (const char *)glGetString(GL_RENDERER);
776     std::string version = (const char *)glGetString(GL_VERSION);
777     int minorVersion = 0;
778     int patchVersion = 0;
779     // try to extract some minor version numbers
780     if (version.find("4.1 ATI-1.") == 0)
781     {
782       std::string minorVer = version.substr(strlen("4.1 ATI-1."),std::string::npos);
783       if (minorVer.find('.') == 2)
784       {
785         minorVersion = atoi(minorVer.substr(0,2).c_str());
786         patchVersion = atoi(minorVer.substr(3,std::string::npos).c_str());
787       }
788     }
789     if (
790         ((version.find("4.1 ATI-1.38.3") != std::string::npos ||
791           version.find("4.1 ATI-1.40.15") != std::string::npos) &&
792           (renderer.find("AMD Radeon R9 M370X OpenGL Engine") != std::string::npos)) ||
793           // assume anything with 1.40.16 or later is good?
794           minorVersion > 40 ||
795           (minorVersion == 40 && patchVersion >= 16)
796          )
797     {
798       this->HaveApplePrimitiveIdBugValue = false;
799     }
800   }
801 
802   // On all versions of macOS and with all GPUs,
803   // allow an env var to force the workaround to be used.
804   const char* forceWorkaround = std::getenv("VTK_FORCE_APPLE_PRIMITIVEID_WORKAROUND");
805   if (forceWorkaround)
806   {
807     this->HaveApplePrimitiveIdBugValue = true;
808   }
809 
810 #else
811   this->HaveApplePrimitiveIdBugValue = false;
812 #endif
813 
814   this->HaveApplePrimitiveIdBugChecked = true;
815   return this->HaveApplePrimitiveIdBugValue;
816 }
817 
818 //------------------------------------------------------------------------------
HaveAppleQueryAllocationBug()819 bool vtkOpenGLRenderer::HaveAppleQueryAllocationBug()
820 {
821 #if defined(__APPLE__) && ! defined(VTK_OPENGL_HAS_OSMESA)
822   enum class QueryAllocStatus { NotChecked, Yes, No };
823   static QueryAllocStatus hasBug = QueryAllocStatus::NotChecked;
824 
825   if (hasBug == QueryAllocStatus::NotChecked)
826   {
827     // We can restrict this to a specific version, etc, as we get more
828     // information about the bug, but for now just disable query allocations on
829     // all apple NVIDIA cards.
830     std::string v = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
831     hasBug = (v.find("NVIDIA") != std::string::npos) ? QueryAllocStatus::Yes
832                                                      : QueryAllocStatus::No;
833   }
834 
835   return hasBug == QueryAllocStatus::Yes;
836 #else
837   return false;
838 #endif
839 }
840 
841 //------------------------------------------------------------------------------
IsDualDepthPeelingSupported()842 bool vtkOpenGLRenderer::IsDualDepthPeelingSupported()
843 {
844   vtkOpenGLRenderWindow *context
845     = vtkOpenGLRenderWindow::SafeDownCast(this->RenderWindow);
846   if (!context)
847   {
848     vtkDebugMacro("Cannot determine if dual depth peeling is support -- no "
849                   "vtkRenderWindow set.");
850     return false;
851   }
852 
853   // Dual depth peeling requires:
854   // - float textures (ARB_texture_float)
855   // - RG textures (ARB_texture_rg)
856   // - MAX blending (added in ES3).
857   // requires that RG textures be color renderable (they are not in ES3)
858 #if GL_ES_VERSION_3_0 == 1
859   // ES3 is not supported, see TestFramebufferPass.cxx for how to do it
860   bool dualDepthPeelingSupported = false;
861 #else
862   bool dualDepthPeelingSupported = true;
863 #endif
864 
865   // There's a bug on current mesa master that prevents dual depth peeling
866   // from functioning properly, something in the texture sampler is causing
867   // all lookups to return NaN. See discussion on
868   // https://bugs.freedesktop.org/show_bug.cgi?id=94955
869   // This has been fixed in Mesa 17.2.
870   const char *glVersionC =
871       reinterpret_cast<const char *>(glGetString(GL_VERSION));
872   std::string glVersion = std::string(glVersionC ? glVersionC : "");
873   if (dualDepthPeelingSupported &&
874       glVersion.find("Mesa") != std::string::npos)
875   {
876     bool mesaCompat = false;
877     // The bug has been fixed with mesa 17.2.0. The version string is approx:
878     // 3.3 (Core Profile) Mesa 17.2.0-devel (git-08cb8cf256)
879     vtksys::RegularExpression re("Mesa ([0-9]+)\\.([0-9]+)\\.");
880     if (re.find(glVersion))
881     {
882       int majorVersion;
883       std::string majorStr = re.match(1);
884       std::istringstream majorParse(majorStr);
885       majorParse >> majorVersion;
886       if (majorVersion > 17)
887       {
888         mesaCompat = true;
889       }
890       else if (majorVersion == 17)
891       {
892         int minorVersion;
893         std::string minorStr = re.match(2);
894         std::istringstream minorParse(minorStr);
895         minorParse >> minorVersion;
896         if (minorVersion >= 2)
897         {
898           mesaCompat = true;
899         }
900       }
901     }
902 
903     if (!mesaCompat)
904     {
905       vtkDebugMacro("Disabling dual depth peeling -- mesa bug detected. "
906                     "GL_VERSION = '" << glVersion << "'.");
907       dualDepthPeelingSupported = false;
908     }
909   }
910 
911   // The old implementation can be forced by defining the environment var
912   // "VTK_USE_LEGACY_DEPTH_PEELING":
913   if (dualDepthPeelingSupported)
914   {
915     const char *forceLegacy = getenv("VTK_USE_LEGACY_DEPTH_PEELING");
916     if (forceLegacy)
917     {
918       vtkDebugMacro("Disabling dual depth peeling -- "
919                     "VTK_USE_LEGACY_DEPTH_PEELING defined in environment.");
920       dualDepthPeelingSupported = false;
921     }
922   }
923 
924   return dualDepthPeelingSupported;
925 }
926 
GetState()927 vtkOpenGLState *vtkOpenGLRenderer::GetState()
928 {
929   return this->VTKWindow ? static_cast<vtkOpenGLRenderWindow *>(this->VTKWindow)->GetState() : nullptr;
930 }
931 
GetLightingUniforms()932 const char *vtkOpenGLRenderer::GetLightingUniforms()
933 {
934   return this->LightingDeclaration.c_str();
935 }
936 
UpdateLightingUniforms(vtkShaderProgram * program)937 void vtkOpenGLRenderer::UpdateLightingUniforms(vtkShaderProgram *program)
938 {
939   vtkMTimeType ptime = program->GetUniformGroupUpdateTime(vtkShaderProgram::LightingGroup);
940   vtkMTimeType ltime = this->LightingUpdateTime;
941 
942   // for lighting complexity 2,3 camera has an impact
943   vtkCamera *cam = this->GetActiveCamera();
944   if (this->LightingComplexity > 1)
945   {
946     ltime = vtkMath::Max(ltime, cam->GetMTime());
947   }
948 
949   if (ltime <= ptime)
950   {
951     return;
952   }
953 
954   // for lightkit case there are some parameters to set
955   vtkTransform* viewTF = cam->GetModelViewTransformObject();
956 
957   // bind some light settings
958   int numberOfLights = 0;
959   vtkLightCollection *lc = this->GetLights();
960   vtkLight *light;
961 
962   vtkCollectionSimpleIterator sit;
963   float lightColor[3];
964   float lightDirection[3];
965   std::string lcolor("lightColor");
966   std::string ldir("lightDirectionVC");
967   std::string latten("lightAttenuation");
968   std::string lpositional("lightPositional");
969   std::string lpos("lightPositionVC");
970   std::string lexp("lightExponent");
971   std::string lcone("lightConeAngle");
972 
973   std::ostringstream toString;
974   for (lc->InitTraversal(sit); (light = lc->GetNextLight(sit)); )
975   {
976     float status = light->GetSwitch();
977     if (status > 0.0)
978     {
979       toString.str("");
980       toString << numberOfLights;
981       std::string count = toString.str();
982 
983       double *dColor = light->GetDiffuseColor();
984       double intensity = light->GetIntensity();
985       // if (renderLuminance)
986       // {
987       //   lightColor[0] = intensity;
988       //   lightColor[1] = intensity;
989       //   lightColor[2] = intensity;
990       // }
991       // else
992       {
993         lightColor[0] = dColor[0] * intensity;
994         lightColor[1] = dColor[1] * intensity;
995         lightColor[2] = dColor[2] * intensity;
996       }
997       program->SetUniform3f((lcolor + count).c_str(), lightColor);
998 
999       // we are done unless we have non headlights
1000       if (this->LightingComplexity >= 2)
1001       {
1002         // get required info from light
1003         double *lfp = light->GetTransformedFocalPoint();
1004         double *lp = light->GetTransformedPosition();
1005         double lightDir[3];
1006         vtkMath::Subtract(lfp,lp,lightDir);
1007         vtkMath::Normalize(lightDir);
1008         double tDirView[3];
1009         viewTF->TransformNormal(lightDir, tDirView);
1010 
1011         if (!light->LightTypeIsSceneLight() && this->UserLightTransform.GetPointer() != nullptr)
1012         {
1013           double *tDir = this->UserLightTransform->TransformNormal(tDirView);
1014           lightDirection[0] = tDir[0];
1015           lightDirection[1] = tDir[1];
1016           lightDirection[2] = tDir[2];
1017         }
1018         else
1019         {
1020           lightDirection[0] = tDirView[0];
1021           lightDirection[1] = tDirView[1];
1022           lightDirection[2] = tDirView[2];
1023         }
1024 
1025         program->SetUniform3f((ldir + count).c_str(), lightDirection);
1026 
1027         // we are done unless we have positional lights
1028         if (this->LightingComplexity >= 3)
1029         {
1030           // if positional lights pass down more parameters
1031           float lightAttenuation[3];
1032           float lightPosition[3];
1033           double *attn = light->GetAttenuationValues();
1034           lightAttenuation[0] = attn[0];
1035           lightAttenuation[1] = attn[1];
1036           lightAttenuation[2] = attn[2];
1037           double tlpView[3];
1038           viewTF->TransformPoint(lp, tlpView);
1039           if (!light->LightTypeIsSceneLight() && this->UserLightTransform.GetPointer() != nullptr)
1040           {
1041             double *tlp = this->UserLightTransform->TransformPoint(tlpView);
1042             lightPosition[0] = tlp[0];
1043             lightPosition[1] = tlp[1];
1044             lightPosition[2] = tlp[2];
1045           }
1046           else
1047           {
1048             lightPosition[0] = tlpView[0];
1049             lightPosition[1] = tlpView[1];
1050             lightPosition[2] = tlpView[2];
1051           }
1052 
1053           program->SetUniform3f((latten + count).c_str(), lightAttenuation);
1054           program->SetUniformi((lpositional + count).c_str(), light->GetPositional());
1055           program->SetUniform3f((lpos + count).c_str(), lightPosition);
1056           program->SetUniformf((lexp + count).c_str(), light->GetExponent());
1057           program->SetUniformf((lcone + count).c_str(), light->GetConeAngle());
1058         }
1059       }
1060       numberOfLights++;
1061     }
1062   }
1063 
1064   program->SetUniformGroupUpdateTime(vtkShaderProgram::LightingGroup, ltime);
1065 }
1066 
SetUserLightTransform(vtkTransform * transform)1067 void vtkOpenGLRenderer::SetUserLightTransform(vtkTransform* transform)
1068 {
1069   this->UserLightTransform = transform;
1070 }
1071