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