1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkOpenGLGPUVolumeRayCastMapper.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 "vtkOpenGLGPUVolumeRayCastMapper.h"
17 
18 #include <vtk_glew.h>
19 
20 #include "vtkVolumeShaderComposer.h"
21 #include "vtkVolumeStateRAII.h"
22 
23 // Include compiled shader code
24 #include <raycasterfs.h>
25 #include <raycastervs.h>
26 
27 // VTK includes
28 #include "vtkInformation.h"
29 #include "vtkOpenGLActor.h"
30 #include "vtkOpenGLResourceFreeCallback.h"
31 #include "vtkOpenGLState.h"
32 #include "vtkOpenGLUniforms.h"
33 #include <vtkBoundingBox.h>
34 #include <vtkCamera.h>
35 #include <vtkCellArray.h>
36 #include <vtkCellData.h>
37 #include <vtkClipConvexPolyData.h>
38 #include <vtkColorTransferFunction.h>
39 #include <vtkCommand.h>
40 #include <vtkContourFilter.h>
41 #include <vtkDataArray.h>
42 #include <vtkDensifyPolyData.h>
43 #include <vtkFloatArray.h>
44 #include <vtkImageData.h>
45 #include <vtkLight.h>
46 #include <vtkLightCollection.h>
47 #include <vtkMath.h>
48 #include <vtkMatrix4x4.h>
49 #include <vtkMultiVolume.h>
50 #include <vtkNew.h>
51 #include <vtkObjectFactory.h>
52 #include <vtkOpenGLBufferObject.h>
53 #include <vtkOpenGLCamera.h>
54 #include <vtkOpenGLError.h>
55 #include <vtkOpenGLFramebufferObject.h>
56 #include <vtkOpenGLRenderPass.h>
57 #include <vtkOpenGLRenderUtilities.h>
58 #include <vtkOpenGLRenderWindow.h>
59 #include <vtkOpenGLShaderCache.h>
60 #include <vtkOpenGLShaderProperty.h>
61 #include <vtkOpenGLVertexArrayObject.h>
62 #include <vtkPixelBufferObject.h>
63 #include <vtkPixelExtent.h>
64 #include <vtkPixelTransfer.h>
65 #include <vtkPlaneCollection.h>
66 #include <vtkPointData.h>
67 #include <vtkPoints.h>
68 #include <vtkPolyData.h>
69 #include <vtkPolyDataMapper.h>
70 #include <vtkRectilinearGrid.h>
71 #include <vtkRenderWindow.h>
72 #include <vtkRenderer.h>
73 #include <vtkShader.h>
74 #include <vtkShaderProgram.h>
75 #include <vtkSmartPointer.h>
76 #include <vtkTessellatedBoxSource.h>
77 #include <vtkTextureObject.h>
78 #include <vtkTimerLog.h>
79 #include <vtkTransform.h>
80 #include <vtkUnsignedCharArray.h>
81 #include <vtkUnsignedIntArray.h>
82 
83 #include <vtkVolumeInputHelper.h>
84 
85 #include "vtkOpenGLVolumeGradientOpacityTable.h"
86 #include "vtkOpenGLVolumeMaskGradientOpacityTransferFunction2D.h"
87 #include "vtkOpenGLVolumeMaskTransferFunction2D.h"
88 #include "vtkOpenGLVolumeOpacityTable.h"
89 #include "vtkOpenGLVolumeRGBTable.h"
90 #include "vtkOpenGLVolumeTransferFunction2D.h"
91 
92 #include <vtkHardwareSelector.h>
93 #include <vtkVolumeMask.h>
94 #include <vtkVolumeProperty.h>
95 #include <vtkVolumeTexture.h>
96 #include <vtkWeakPointer.h>
97 
98 // C/C++ includes
99 #include <cassert>
100 #include <limits>
101 #include <map>
102 #include <sstream>
103 #include <string>
104 
105 vtkStandardNewMacro(vtkOpenGLGPUVolumeRayCastMapper);
106 
107 //------------------------------------------------------------------------------
108 class vtkOpenGLGPUVolumeRayCastMapper::vtkInternal
109 {
110 public:
111   // Constructor
112   //--------------------------------------------------------------------------
vtkInternal(vtkOpenGLGPUVolumeRayCastMapper * parent)113   vtkInternal(vtkOpenGLGPUVolumeRayCastMapper* parent)
114   {
115     this->Parent = parent;
116     this->ValidTransferFunction = false;
117     this->LoadDepthTextureExtensionsSucceeded = false;
118     this->CameraWasInsideInLastUpdate = false;
119     this->CubeVBOId = 0;
120     this->CubeVAOId = 0;
121     this->CubeIndicesId = 0;
122     this->DepthTextureObject = nullptr;
123     this->DepthCopyColorTextureObject = nullptr;
124     this->DepthCopyFBO = nullptr;
125     this->SharedDepthTextureObject = false;
126     this->TextureWidth = 1024;
127     this->ActualSampleDistance = 1.0;
128     this->CurrentMask = nullptr;
129     this->TextureSize[0] = this->TextureSize[1] = this->TextureSize[2] = -1;
130     this->WindowLowerLeft[0] = this->WindowLowerLeft[1] = 0;
131     this->WindowSize[0] = this->WindowSize[1] = 0;
132     this->LastDepthPassWindowSize[0] = this->LastDepthPassWindowSize[1] = 0;
133     this->LastRenderToImageWindowSize[0] = 0;
134     this->LastRenderToImageWindowSize[1] = 0;
135     this->CurrentSelectionPass = vtkHardwareSelector::MIN_KNOWN_PASS - 1;
136 
137     this->NumberOfLights = 0;
138     this->LightComplexity = 0;
139 
140     this->NeedToInitializeResources = false;
141     this->ShaderCache = nullptr;
142 
143     this->FBO = nullptr;
144     this->RTTDepthBufferTextureObject = nullptr;
145     this->RTTDepthTextureObject = nullptr;
146     this->RTTColorTextureObject = nullptr;
147     this->RTTDepthTextureType = -1;
148 
149     this->DPFBO = nullptr;
150     this->DPDepthBufferTextureObject = nullptr;
151     this->DPColorTextureObject = nullptr;
152     this->PreserveViewport = false;
153     this->PreserveGLState = false;
154 
155     this->Partitions[0] = this->Partitions[1] = this->Partitions[2] = 1;
156   }
157 
158   // Destructor
159   //--------------------------------------------------------------------------
~vtkInternal()160   ~vtkInternal()
161   {
162     if (this->DepthTextureObject)
163     {
164       this->DepthTextureObject->Delete();
165       this->DepthTextureObject = nullptr;
166     }
167 
168     if (this->FBO)
169     {
170       this->FBO->Delete();
171       this->FBO = nullptr;
172     }
173 
174     if (this->RTTDepthBufferTextureObject)
175     {
176       this->RTTDepthBufferTextureObject->Delete();
177       this->RTTDepthBufferTextureObject = nullptr;
178     }
179 
180     if (this->RTTDepthTextureObject)
181     {
182       this->RTTDepthTextureObject->Delete();
183       this->RTTDepthTextureObject = nullptr;
184     }
185 
186     if (this->RTTColorTextureObject)
187     {
188       this->RTTColorTextureObject->Delete();
189       this->RTTColorTextureObject = nullptr;
190     }
191 
192     if (this->ImageSampleFBO)
193     {
194       this->ImageSampleFBO->Delete();
195       this->ImageSampleFBO = nullptr;
196     }
197 
198     for (auto& tex : this->ImageSampleTexture)
199     {
200       tex = nullptr;
201     }
202     this->ImageSampleTexture.clear();
203     this->ImageSampleTexNames.clear();
204 
205     if (this->ImageSampleVAO)
206     {
207       this->ImageSampleVAO->Delete();
208       this->ImageSampleVAO = nullptr;
209     }
210     this->DeleteMaskTransfer();
211 
212     // Do not delete the shader programs - Let the cache clean them up.
213     this->ImageSampleProg = nullptr;
214   }
215 
216   // Helper methods
217   //--------------------------------------------------------------------------
218   template <typename T>
219   static void ToFloat(const T& in1, const T& in2, float (&out)[2]);
220   template <typename T>
221   static void ToFloat(const T& in1, const T& in2, const T& in3, float (&out)[3]);
222   template <typename T>
223   static void ToFloat(T* in, float* out, int noOfComponents);
224   template <typename T>
225   static void ToFloat(T (&in)[3], float (&out)[3]);
226   template <typename T>
227   static void ToFloat(T (&in)[2], float (&out)[2]);
228   template <typename T>
229   static void ToFloat(T& in, float& out);
230   template <typename T>
231   static void ToFloat(T (&in)[4][2], float (&out)[4][2]);
232   template <typename T, int SizeX, int SizeY>
233   static void CopyMatrixToVector(T* matrix, float* matrixVec, int offset);
234   template <typename T, int SizeSrc>
235   static void CopyVector(T* srcVec, T* dstVec, int offset);
236 
237   ///@{
238   /**
239    * \brief Setup and clean-up transfer functions for each vtkVolumeInputHelper
240    * and masks.
241    */
242   void UpdateTransferFunctions(vtkRenderer* ren);
243 
244   void RefreshMaskTransfer(vtkRenderer* ren, VolumeInput& input);
245   int UpdateMaskTransfer(vtkRenderer* ren, vtkVolume* vol, unsigned int component);
246   void SetupMaskTransfer(vtkRenderer* ren);
247   void ReleaseGraphicsMaskTransfer(vtkWindow* window);
248   void DeleteMaskTransfer();
249   ///@}
250 
251   void UpdateTransfer2DYAxisArray(vtkRenderer* ren, vtkVolume* vol);
252 
253   bool LoadMask(vtkRenderer* ren);
254 
255   // Update the depth sampler with the current state of the z-buffer. The
256   // sampler is used for z-buffer compositing with opaque geometry during
257   // ray-casting (rays are early-terminated if hidden begin opaque geometry).
258   void CaptureDepthTexture(vtkRenderer* ren);
259 
260   // Test if camera is inside the volume geometry
261   bool IsCameraInside(vtkRenderer* ren, vtkVolume* vol, double geometry[24]);
262 
263   //@{
264   /**
265    * Update volume's proxy-geometry and draw it
266    */
267   bool IsGeometryUpdateRequired(vtkRenderer* ren, vtkVolume* vol, double geometry[24]);
268   void RenderVolumeGeometry(
269     vtkRenderer* ren, vtkShaderProgram* prog, vtkVolume* vol, double geometry[24]);
270   //@}
271 
272   // Update cropping params to shader
273   void SetCroppingRegions(vtkShaderProgram* prog, double loadedBounds[6]);
274 
275   // Update clipping params to shader
276   void SetClippingPlanes(vtkRenderer* ren, vtkShaderProgram* prog, vtkVolume* vol);
277 
278   // Update the ray sampling distance. Sampling distance should be updated
279   // before updating opacity transfer functions.
280   void UpdateSamplingDistance(vtkRenderer* ren);
281 
282   // Check if the mapper should enter picking mode.
283   void CheckPickingState(vtkRenderer* ren);
284 
285   // Look for property keys used to control the mapper's state.
286   // This is necessary for some render passes which need to ensure
287   // a specific OpenGL state when rendering through this mapper.
288   void CheckPropertyKeys(vtkVolume* vol);
289 
290   // Configure the vtkHardwareSelector to begin a picking pass. This call
291   // changes GL_BLEND, so it needs to be called before constructing
292   // vtkVolumeStateRAII.
293   void BeginPicking(vtkRenderer* ren);
294 
295   // Update the prop Id if hardware selection is enabled.
296   void SetPickingId(vtkRenderer* ren);
297 
298   // Configure the vtkHardwareSelector to end a picking pass.
299   void EndPicking(vtkRenderer* ren);
300 
301   // Load OpenGL extensiosn required to grab depth sampler buffer
302   void LoadRequireDepthTextureExtensions(vtkRenderWindow* renWin);
303 
304   // Create GL buffers
305   void CreateBufferObjects();
306 
307   // Dispose / free GL buffers
308   void DeleteBufferObjects();
309 
310   // Convert vtkTextureObject to vtkImageData
311   void ConvertTextureToImageData(vtkTextureObject* texture, vtkImageData* output);
312 
313   // Render to texture for final rendering
314   void SetupRenderToTexture(vtkRenderer* ren);
315   void ExitRenderToTexture(vtkRenderer* ren);
316 
317   // Render to texture for depth pass
318   void SetupDepthPass(vtkRenderer* ren);
319   void RenderContourPass(vtkRenderer* ren);
320   void ExitDepthPass(vtkRenderer* ren);
321   void RenderWithDepthPass(vtkRenderer* ren, vtkOpenGLCamera* cam, vtkMTimeType renderPassTime);
322 
323   void RenderSingleInput(vtkRenderer* ren, vtkOpenGLCamera* cam, vtkShaderProgram* prog);
324 
325   void RenderMultipleInputs(vtkRenderer* ren, vtkOpenGLCamera* cam, vtkShaderProgram* prog);
326 
327   //@{
328   /**
329    * Update shader parameters.
330    */
331   void SetLightingShaderParameters(
332     vtkRenderer* ren, vtkShaderProgram* prog, vtkVolume* vol, int numberOfSamplers);
333 
334   /**
335    * Global parameters.
336    */
337   void SetMapperShaderParameters(
338     vtkShaderProgram* prog, vtkRenderer* ren, int independent, int numComponents);
339 
340   /**
341    * Per input data/ per component parameters.
342    */
343   void SetVolumeShaderParameters(
344     vtkShaderProgram* prog, int independent, int noOfComponents, vtkMatrix4x4* modelViewMat);
345   void BindTransformations(vtkShaderProgram* prog, vtkMatrix4x4* modelViewMat);
346 
347   /**
348    * Transformation parameters.
349    */
350   void SetCameraShaderParameters(vtkShaderProgram* prog, vtkRenderer* ren, vtkOpenGLCamera* cam);
351 
352   /**
353    * Feature specific.
354    */
355   void SetMaskShaderParameters(vtkShaderProgram* prog, vtkVolumeProperty* prop, int noOfComponents);
356   void SetRenderToImageParameters(vtkShaderProgram* prog);
357   void SetAdvancedShaderParameters(vtkRenderer* ren, vtkShaderProgram* prog, vtkVolume* vol,
358     vtkVolumeTexture::VolumeBlock* block, int numComp);
359   //@}
360 
361   void FinishRendering(int numComponents);
362 
363   inline bool ShaderRebuildNeeded(vtkCamera* cam, vtkVolume* vol, vtkMTimeType renderPassTime);
364   bool VolumePropertyChanged = true;
365 
366   //@{
367   /**
368    * Image XY-Sampling
369    * Render to an internal framebuffer with lower resolution than the currently
370    * bound one (hence casting less rays and improving performance). The rendered
371    * image is subsequently rendered as a texture-mapped quad (linearly
372    * interpolated) to the default (or previously attached) framebuffer. If a
373    * vtkOpenGLRenderPass is attached, a variable number of render targets are
374    * supported (as specified by the RenderPass). The render targets are assumed
375    * to be ordered from GL_COLOR_ATTACHMENT0 to GL_COLOR_ATTACHMENT$N$, where
376    * $N$ is the number of targets specified (targets of the previously bound
377    * framebuffer as activated through ActivateDrawBuffers(int)). Without a
378    * RenderPass attached, it relies on FramebufferObject to re-activate the
379    * appropriate previous DrawBuffer.
380    *
381    * \sa vtkOpenGLRenderPass vtkOpenGLFramebufferObject
382    */
383   void BeginImageSample(vtkRenderer* ren);
384   bool InitializeImageSampleFBO(vtkRenderer* ren);
385   void EndImageSample(vtkRenderer* ren);
386   size_t GetNumImageSampleDrawBuffers(vtkVolume* vol);
387   //@}
388 
389   //@{
390   /**
391    * Allocate and update input data. A list of active ports is maintained
392    * by the parent class. This list is traversed to update internal structures
393    * used during rendering.
394    */
395   bool UpdateInputs(vtkRenderer* ren, vtkVolume* vol);
396 
397   /**
398    * Cleanup resources of inputs that have been removed.
399    */
400   void ClearRemovedInputs(vtkWindow* win);
401 
402   /**
403    * Forces transfer functions in all of the active vtkVolumeInputHelpers to
404    * re-initialize in the next update. This is essential if the order in
405    * AssembledInputs changes (inputs are added or removed), given that variable
406    * names cached in vtkVolumeInputHelper instances are indexed.
407    */
408   void ForceTransferInit();
409   //@}
410 
GetActiveVolume()411   vtkVolume* GetActiveVolume()
412   {
413     return this->MultiVolume ? this->MultiVolume : this->Parent->AssembledInputs[0].Volume;
414   }
415   int GetComponentMode(vtkVolumeProperty* prop, vtkDataArray* array) const;
416 
417   void ReleaseRenderToTextureGraphicsResources(vtkWindow* win);
418   void ReleaseImageSampleGraphicsResources(vtkWindow* win);
419   void ReleaseDepthPassGraphicsResources(vtkWindow* win);
420 
421   // Private member variables
422   //--------------------------------------------------------------------------
423   vtkOpenGLGPUVolumeRayCastMapper* Parent;
424 
425   bool ValidTransferFunction;
426   bool LoadDepthTextureExtensionsSucceeded;
427   bool CameraWasInsideInLastUpdate;
428 
429   GLuint CubeVBOId;
430   GLuint CubeVAOId;
431   GLuint CubeIndicesId;
432 
433   vtkTextureObject* DepthTextureObject;
434   vtkTextureObject* DepthCopyColorTextureObject;
435   vtkOpenGLFramebufferObject* DepthCopyFBO;
436   bool SharedDepthTextureObject;
437 
438   int TextureWidth;
439 
440   float ActualSampleDistance;
441 
442   int LastProjectionParallel;
443   int TextureSize[3];
444   int WindowLowerLeft[2];
445   int WindowSize[2];
446   int LastDepthPassWindowSize[2];
447   int LastRenderToImageWindowSize[2];
448 
449   int NumberOfLights;
450   int LightComplexity;
451 
452   std::ostringstream ExtensionsStringStream;
453 
454   vtkSmartPointer<vtkOpenGLVolumeMaskTransferFunction2D> LabelMapTransfer2D;
455   vtkSmartPointer<vtkOpenGLVolumeMaskGradientOpacityTransferFunction2D> LabelMapGradientOpacity;
456 
457   vtkTimeStamp ShaderBuildTime;
458 
459   vtkNew<vtkMatrix4x4> InverseProjectionMat;
460   vtkNew<vtkMatrix4x4> InverseModelViewMat;
461   vtkNew<vtkMatrix4x4> InverseVolumeMat;
462 
463   vtkSmartPointer<vtkPolyData> BBoxPolyData;
464   vtkSmartPointer<vtkVolumeTexture> CurrentMask;
465 
466   vtkTimeStamp InitializationTime;
467   vtkTimeStamp MaskUpdateTime;
468   vtkTimeStamp ReleaseResourcesTime;
469   vtkTimeStamp DepthPassTime;
470   vtkTimeStamp DepthPassSetupTime;
471   vtkTimeStamp SelectionStateTime;
472   int CurrentSelectionPass;
473   bool IsPicking;
474 
475   bool NeedToInitializeResources;
476   bool PreserveViewport;
477   bool PreserveGLState;
478 
479   vtkShaderProgram* ShaderProgram;
480   vtkOpenGLShaderCache* ShaderCache;
481 
482   vtkOpenGLFramebufferObject* FBO;
483   vtkTextureObject* RTTDepthBufferTextureObject;
484   vtkTextureObject* RTTDepthTextureObject;
485   vtkTextureObject* RTTColorTextureObject;
486   int RTTDepthTextureType;
487 
488   vtkOpenGLFramebufferObject* DPFBO;
489   vtkTextureObject* DPDepthBufferTextureObject;
490   vtkTextureObject* DPColorTextureObject;
491 
492   vtkOpenGLFramebufferObject* ImageSampleFBO = nullptr;
493   std::vector<vtkSmartPointer<vtkTextureObject>> ImageSampleTexture;
494   std::vector<std::string> ImageSampleTexNames;
495   vtkShaderProgram* ImageSampleProg = nullptr;
496   vtkOpenGLVertexArrayObject* ImageSampleVAO = nullptr;
497   size_t NumImageSampleDrawBuffers = 0;
498   bool RebuildImageSampleProg = false;
499   bool RenderPassAttached = false;
500 
501   bool Transfer2DUseGradient = true;
502   vtkSmartPointer<vtkVolumeTexture> Transfer2DYAxisScalars;
503   vtkTimeStamp Transfer2DYAxisScalarsUpdateTime;
504 
505   vtkNew<vtkContourFilter> ContourFilter;
506   vtkNew<vtkPolyDataMapper> ContourMapper;
507   vtkNew<vtkActor> ContourActor;
508 
509   unsigned short Partitions[3];
510   vtkMultiVolume* MultiVolume = nullptr;
511 
512   std::vector<float> VolMatVec, InvMatVec, TexMatVec, InvTexMatVec, TexEyeMatVec, CellToPointVec,
513     TexMinVec, TexMaxVec, ScaleVec, BiasVec, StepVec, SpacingVec, RangeVec;
514 };
515 
516 //------------------------------------------------------------------------------
517 template <typename T>
ToFloat(const T & in1,const T & in2,float (& out)[2])518 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ToFloat(
519   const T& in1, const T& in2, float (&out)[2])
520 {
521   out[0] = static_cast<float>(in1);
522   out[1] = static_cast<float>(in2);
523 }
524 
525 template <typename T>
ToFloat(const T & in1,const T & in2,const T & in3,float (& out)[3])526 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ToFloat(
527   const T& in1, const T& in2, const T& in3, float (&out)[3])
528 {
529   out[0] = static_cast<float>(in1);
530   out[1] = static_cast<float>(in2);
531   out[2] = static_cast<float>(in3);
532 }
533 
534 //------------------------------------------------------------------------------
535 template <typename T>
ToFloat(T * in,float * out,int noOfComponents)536 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ToFloat(T* in, float* out, int noOfComponents)
537 {
538   for (int i = 0; i < noOfComponents; ++i)
539   {
540     out[i] = static_cast<float>(in[i]);
541   }
542 }
543 
544 //------------------------------------------------------------------------------
545 template <typename T>
ToFloat(T (& in)[3],float (& out)[3])546 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ToFloat(T (&in)[3], float (&out)[3])
547 {
548   out[0] = static_cast<float>(in[0]);
549   out[1] = static_cast<float>(in[1]);
550   out[2] = static_cast<float>(in[2]);
551 }
552 
553 //------------------------------------------------------------------------------
554 template <typename T>
ToFloat(T (& in)[2],float (& out)[2])555 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ToFloat(T (&in)[2], float (&out)[2])
556 {
557   out[0] = static_cast<float>(in[0]);
558   out[1] = static_cast<float>(in[1]);
559 }
560 
561 //------------------------------------------------------------------------------
562 template <typename T>
ToFloat(T & in,float & out)563 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ToFloat(T& in, float& out)
564 {
565   out = static_cast<float>(in);
566 }
567 
568 //------------------------------------------------------------------------------
569 template <typename T>
ToFloat(T (& in)[4][2],float (& out)[4][2])570 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ToFloat(T (&in)[4][2], float (&out)[4][2])
571 {
572   out[0][0] = static_cast<float>(in[0][0]);
573   out[0][1] = static_cast<float>(in[0][1]);
574   out[1][0] = static_cast<float>(in[1][0]);
575   out[1][1] = static_cast<float>(in[1][1]);
576   out[2][0] = static_cast<float>(in[2][0]);
577   out[2][1] = static_cast<float>(in[2][1]);
578   out[3][0] = static_cast<float>(in[3][0]);
579   out[3][1] = static_cast<float>(in[3][1]);
580 }
581 
582 //------------------------------------------------------------------------------
583 template <typename T, int SizeX, int SizeY>
CopyMatrixToVector(T * matrix,float * matrixVec,int offset)584 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::CopyMatrixToVector(
585   T* matrix, float* matrixVec, int offset)
586 {
587   const int MatSize = SizeX * SizeY;
588   for (int j = 0; j < MatSize; j++)
589   {
590     matrixVec[offset + j] = matrix->Element[j / SizeX][j % SizeY];
591   }
592 }
593 
594 //------------------------------------------------------------------------------
595 template <typename T, int SizeSrc>
CopyVector(T * srcVec,T * dstVec,int offset)596 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::CopyVector(T* srcVec, T* dstVec, int offset)
597 {
598   for (int j = 0; j < SizeSrc; j++)
599   {
600     dstVec[offset + j] = srcVec[j];
601   }
602 }
603 
604 //------------------------------------------------------------------------------
SetupMaskTransfer(vtkRenderer * ren)605 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetupMaskTransfer(vtkRenderer* ren)
606 {
607   this->ReleaseGraphicsMaskTransfer(ren->GetRenderWindow());
608   this->DeleteMaskTransfer();
609 
610   if (this->Parent->MaskInput != nullptr && this->Parent->MaskType == LabelMapMaskType &&
611     !this->LabelMapTransfer2D)
612   {
613     this->LabelMapTransfer2D = vtkSmartPointer<vtkOpenGLVolumeMaskTransferFunction2D>::New();
614     this->LabelMapGradientOpacity =
615       vtkSmartPointer<vtkOpenGLVolumeMaskGradientOpacityTransferFunction2D>::New();
616   }
617 
618   this->InitializationTime.Modified();
619 }
620 
621 //------------------------------------------------------------------------------
RefreshMaskTransfer(vtkRenderer * ren,VolumeInput & input)622 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::RefreshMaskTransfer(
623   vtkRenderer* ren, VolumeInput& input)
624 {
625   auto vol = input.Volume;
626   if (this->NeedToInitializeResources ||
627     input.Volume->GetProperty()->GetMTime() > this->InitializationTime.GetMTime())
628   {
629     this->SetupMaskTransfer(ren);
630   }
631   this->UpdateMaskTransfer(ren, vol, 0);
632 }
633 
634 //------------------------------------------------------------------------------
UpdateTransferFunctions(vtkRenderer * ren)635 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::UpdateTransferFunctions(vtkRenderer* ren)
636 {
637   int uniformIndex = 0;
638   for (const auto& port : this->Parent->Ports)
639   {
640     auto& input = this->Parent->AssembledInputs[port];
641     input.ColorRangeType = this->Parent->GetColorRangeType();
642     input.ScalarOpacityRangeType = this->Parent->GetScalarOpacityRangeType();
643     input.GradientOpacityRangeType = this->Parent->GetGradientOpacityRangeType();
644     input.RefreshTransferFunction(
645       ren, uniformIndex, this->Parent->BlendMode, this->ActualSampleDistance);
646 
647     uniformIndex++;
648   }
649 
650   if (!this->MultiVolume)
651   {
652     this->RefreshMaskTransfer(ren, this->Parent->AssembledInputs[0]);
653   }
654 }
655 
656 //------------------------------------------------------------------------------
LoadMask(vtkRenderer * ren)657 bool vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::LoadMask(vtkRenderer* ren)
658 {
659   bool result = true;
660   auto maskInput = this->Parent->MaskInput;
661   if (maskInput)
662   {
663     if (!this->CurrentMask)
664     {
665       this->CurrentMask = vtkSmartPointer<vtkVolumeTexture>::New();
666 
667       const auto part = this->Partitions;
668       this->CurrentMask->SetPartitions(part[0], part[1], part[2]);
669     }
670 
671     int isCellData;
672     vtkDataArray* arr =
673       vtkOpenGLGPUVolumeRayCastMapper::GetScalars(maskInput, this->Parent->ScalarMode,
674         this->Parent->ArrayAccessMode, this->Parent->ArrayId, this->Parent->ArrayName, isCellData);
675     if (maskInput->GetMTime() > this->MaskUpdateTime ||
676       this->CurrentMask->GetLoadedScalars() != arr ||
677       (arr && arr->GetMTime() > this->MaskUpdateTime))
678     {
679       result =
680         this->CurrentMask->LoadVolume(ren, maskInput, arr, isCellData, VTK_NEAREST_INTERPOLATION);
681 
682       this->MaskUpdateTime.Modified();
683     }
684   }
685 
686   return result;
687 }
688 
689 //------------------------------------------------------------------------------
ReleaseGraphicsMaskTransfer(vtkWindow * window)690 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ReleaseGraphicsMaskTransfer(vtkWindow* window)
691 {
692   if (this->LabelMapTransfer2D)
693   {
694     this->LabelMapTransfer2D->ReleaseGraphicsResources(window);
695   }
696   if (this->LabelMapGradientOpacity)
697   {
698     this->LabelMapGradientOpacity->ReleaseGraphicsResources(window);
699   }
700 }
701 
702 //------------------------------------------------------------------------------
DeleteMaskTransfer()703 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::DeleteMaskTransfer()
704 {
705   this->LabelMapTransfer2D = nullptr;
706   this->LabelMapGradientOpacity = nullptr;
707 }
708 
709 //------------------------------------------------------------------------------
UpdateMaskTransfer(vtkRenderer * ren,vtkVolume * vol,unsigned int component)710 int vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::UpdateMaskTransfer(
711   vtkRenderer* ren, vtkVolume* vol, unsigned int component)
712 {
713   vtkVolumeProperty* volumeProperty = vol->GetProperty();
714 
715   auto volumeTex = this->Parent->AssembledInputs[0].Texture.GetPointer();
716   double componentRange[2];
717   for (int i = 0; i < 2; ++i)
718   {
719     componentRange[i] = volumeTex->ScalarRange[component][i];
720   }
721 
722   if (this->Parent->MaskInput != nullptr && this->Parent->MaskType == LabelMapMaskType)
723   {
724     this->LabelMapTransfer2D->Update(volumeProperty, componentRange, 0, 0, 0,
725       vtkTextureObject::Nearest, vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow()));
726 
727     if (volumeProperty->HasLabelGradientOpacity())
728     {
729       this->LabelMapGradientOpacity->Update(volumeProperty, componentRange, 0, 0, 0,
730         vtkTextureObject::Nearest, vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow()));
731     }
732   }
733 
734   return 0;
735 }
736 
737 //------------------------------------------------------------------------------
CaptureDepthTexture(vtkRenderer * ren)738 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::CaptureDepthTexture(vtkRenderer* ren)
739 {
740   // Make sure our render window is the current OpenGL context
741   ren->GetRenderWindow()->MakeCurrent();
742 
743   // Load required extensions for grabbing depth sampler buffer
744   if (!this->LoadDepthTextureExtensionsSucceeded)
745   {
746     this->LoadRequireDepthTextureExtensions(ren->GetRenderWindow());
747   }
748 
749   // If we can't load the necessary extensions, provide
750   // feedback on why it failed.
751   if (!this->LoadDepthTextureExtensionsSucceeded)
752   {
753     std::cerr << this->ExtensionsStringStream.str() << std::endl;
754     return;
755   }
756 
757   if (!this->DepthTextureObject)
758   {
759     this->DepthTextureObject = vtkTextureObject::New();
760     this->DepthCopyColorTextureObject = vtkTextureObject::New();
761   }
762 
763   vtkOpenGLRenderWindow* orenWin = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
764   this->DepthTextureObject->SetContext(orenWin);
765   this->DepthCopyColorTextureObject->SetContext(orenWin);
766 
767   //  this->DepthTextureObject->Activate();
768   if (!this->DepthTextureObject->GetHandle())
769   {
770     // First set the parameters
771     this->DepthTextureObject->SetWrapS(vtkTextureObject::Repeat);
772     this->DepthTextureObject->SetWrapT(vtkTextureObject::Repeat);
773     this->DepthTextureObject->SetMagnificationFilter(vtkTextureObject::Linear);
774     this->DepthTextureObject->SetMinificationFilter(vtkTextureObject::Linear);
775     if (orenWin->GetStencilCapable())
776     {
777       this->DepthTextureObject->AllocateDepthStencil(this->WindowSize[0], this->WindowSize[1]);
778     }
779     else
780     {
781       this->DepthTextureObject->AllocateDepth(this->WindowSize[0], this->WindowSize[1], 4);
782     }
783   }
784 
785   if (!this->DepthCopyColorTextureObject->GetHandle())
786   {
787     // First set the parameters
788     this->DepthCopyColorTextureObject->SetWrapS(vtkTextureObject::Repeat);
789     this->DepthCopyColorTextureObject->SetWrapT(vtkTextureObject::Repeat);
790     this->DepthCopyColorTextureObject->SetMagnificationFilter(vtkTextureObject::Linear);
791     this->DepthCopyColorTextureObject->SetMinificationFilter(vtkTextureObject::Linear);
792     this->DepthCopyColorTextureObject->Allocate2D(
793       this->WindowSize[0], this->WindowSize[1], 4, VTK_UNSIGNED_CHAR);
794   }
795   this->DepthTextureObject->Resize(this->WindowSize[0], this->WindowSize[1]);
796   this->DepthCopyColorTextureObject->Resize(this->WindowSize[0], this->WindowSize[1]);
797 
798   // copy depth with a blit
799   if (!this->DepthCopyFBO)
800   {
801     this->DepthCopyFBO = vtkOpenGLFramebufferObject::New();
802     this->DepthCopyFBO->SetContext(orenWin);
803     orenWin->GetState()->PushDrawFramebufferBinding();
804     this->DepthCopyFBO->Bind(GL_DRAW_FRAMEBUFFER);
805     this->DepthCopyFBO->AddDepthAttachment(this->DepthTextureObject);
806     this->DepthCopyFBO->AddColorAttachment(0, this->DepthCopyColorTextureObject);
807   }
808   else
809   {
810     orenWin->GetState()->PushDrawFramebufferBinding();
811   }
812 
813   this->DepthCopyFBO->Bind(GL_DRAW_FRAMEBUFFER);
814   orenWin->GetState()->vtkglBlitFramebuffer(this->WindowLowerLeft[0], this->WindowLowerLeft[1],
815     this->WindowLowerLeft[0] + this->WindowSize[0], this->WindowLowerLeft[1] + this->WindowSize[1],
816     0, 0, this->WindowSize[0], this->WindowSize[1], GL_DEPTH_BUFFER_BIT, GL_NEAREST);
817 
818   orenWin->GetState()->PopDrawFramebufferBinding();
819 }
820 
821 //------------------------------------------------------------------------------
SetLightingShaderParameters(vtkRenderer * ren,vtkShaderProgram * prog,vtkVolume * vol,int numberOfSamplers)822 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetLightingShaderParameters(
823   vtkRenderer* ren, vtkShaderProgram* prog, vtkVolume* vol, int numberOfSamplers)
824 {
825   // Set basic lighting parameters (per component)
826   if (!ren || !prog || !vol)
827   {
828     return;
829   }
830 
831   auto volumeProperty = vol->GetProperty();
832   float ambient[4][3];
833   float diffuse[4][3];
834   float specular[4][3];
835   float specularPower[4];
836 
837   for (int i = 0; i < numberOfSamplers; ++i)
838   {
839     ambient[i][0] = ambient[i][1] = ambient[i][2] = volumeProperty->GetAmbient(i);
840     diffuse[i][0] = diffuse[i][1] = diffuse[i][2] = volumeProperty->GetDiffuse(i);
841     specular[i][0] = specular[i][1] = specular[i][2] = volumeProperty->GetSpecular(i);
842     specularPower[i] = volumeProperty->GetSpecularPower(i);
843   }
844 
845   prog->SetUniform3fv("in_ambient", numberOfSamplers, ambient);
846   prog->SetUniform3fv("in_diffuse", numberOfSamplers, diffuse);
847   prog->SetUniform3fv("in_specular", numberOfSamplers, specular);
848   prog->SetUniform1fv("in_shininess", numberOfSamplers, specularPower);
849 
850   // Set advanced lighting features
851   if (vol && !vol->GetProperty()->GetShade())
852   {
853     return;
854   }
855 
856   prog->SetUniformi("in_twoSidedLighting", ren->GetTwoSidedLighting());
857 
858   // for lightkit case there are some parameters to set
859   vtkCamera* cam = ren->GetActiveCamera();
860   vtkTransform* viewTF = cam->GetModelViewTransformObject();
861 
862   // Bind some light settings
863   int numberOfLights = 0;
864   vtkLightCollection* lc = ren->GetLights();
865   vtkLight* light;
866 
867   vtkCollectionSimpleIterator sit;
868   float lightAmbientColor[6][3];
869   float lightDiffuseColor[6][3];
870   float lightSpecularColor[6][3];
871   float lightDirection[6][3];
872   for (lc->InitTraversal(sit); (light = lc->GetNextLight(sit));)
873   {
874     float status = light->GetSwitch();
875     if (status > 0.0)
876     {
877       double* aColor = light->GetAmbientColor();
878       double* dColor = light->GetDiffuseColor();
879       double* sColor = light->GetSpecularColor();
880       double intensity = light->GetIntensity();
881       lightAmbientColor[numberOfLights][0] = aColor[0] * intensity;
882       lightAmbientColor[numberOfLights][1] = aColor[1] * intensity;
883       lightAmbientColor[numberOfLights][2] = aColor[2] * intensity;
884       lightDiffuseColor[numberOfLights][0] = dColor[0] * intensity;
885       lightDiffuseColor[numberOfLights][1] = dColor[1] * intensity;
886       lightDiffuseColor[numberOfLights][2] = dColor[2] * intensity;
887       lightSpecularColor[numberOfLights][0] = sColor[0] * intensity;
888       lightSpecularColor[numberOfLights][1] = sColor[1] * intensity;
889       lightSpecularColor[numberOfLights][2] = sColor[2] * intensity;
890       // Get required info from light
891       double* lfp = light->GetTransformedFocalPoint();
892       double* lp = light->GetTransformedPosition();
893       double lightDir[3];
894       vtkMath::Subtract(lfp, lp, lightDir);
895       vtkMath::Normalize(lightDir);
896       double* tDir = viewTF->TransformNormal(lightDir);
897       lightDirection[numberOfLights][0] = tDir[0];
898       lightDirection[numberOfLights][1] = tDir[1];
899       lightDirection[numberOfLights][2] = tDir[2];
900       numberOfLights++;
901     }
902   }
903 
904   prog->SetUniform3fv("in_lightAmbientColor", numberOfLights, lightAmbientColor);
905   prog->SetUniform3fv("in_lightDiffuseColor", numberOfLights, lightDiffuseColor);
906   prog->SetUniform3fv("in_lightSpecularColor", numberOfLights, lightSpecularColor);
907   prog->SetUniform3fv("in_lightDirection", numberOfLights, lightDirection);
908   prog->SetUniformi("in_numberOfLights", numberOfLights);
909 
910   // we are done unless we have positional lights
911   if (this->LightComplexity < 3)
912   {
913     return;
914   }
915 
916   // if positional lights pass down more parameters
917   float lightAttenuation[6][3];
918   float lightPosition[6][3];
919   float lightConeAngle[6];
920   float lightExponent[6];
921   int lightPositional[6];
922   numberOfLights = 0;
923   for (lc->InitTraversal(sit); (light = lc->GetNextLight(sit));)
924   {
925     float status = light->GetSwitch();
926     if (status > 0.0)
927     {
928       double* attn = light->GetAttenuationValues();
929       lightAttenuation[numberOfLights][0] = attn[0];
930       lightAttenuation[numberOfLights][1] = attn[1];
931       lightAttenuation[numberOfLights][2] = attn[2];
932       lightExponent[numberOfLights] = light->GetExponent();
933       lightConeAngle[numberOfLights] = light->GetConeAngle();
934       double* lp = light->GetTransformedPosition();
935       double* tlp = viewTF->TransformPoint(lp);
936       lightPosition[numberOfLights][0] = tlp[0];
937       lightPosition[numberOfLights][1] = tlp[1];
938       lightPosition[numberOfLights][2] = tlp[2];
939       lightPositional[numberOfLights] = light->GetPositional();
940       numberOfLights++;
941     }
942   }
943   prog->SetUniform3fv("in_lightAttenuation", numberOfLights, lightAttenuation);
944   prog->SetUniform1iv("in_lightPositional", numberOfLights, lightPositional);
945   prog->SetUniform3fv("in_lightPosition", numberOfLights, lightPosition);
946   prog->SetUniform1fv("in_lightExponent", numberOfLights, lightExponent);
947   prog->SetUniform1fv("in_lightConeAngle", numberOfLights, lightConeAngle);
948 }
949 
950 //------------------------------------------------------------------------------
IsCameraInside(vtkRenderer * ren,vtkVolume * vol,double geometry[24])951 bool vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::IsCameraInside(
952   vtkRenderer* ren, vtkVolume* vol, double geometry[24])
953 {
954   vtkNew<vtkMatrix4x4> dataToWorld;
955   dataToWorld->DeepCopy(vol->GetMatrix());
956 
957   vtkCamera* cam = ren->GetActiveCamera();
958 
959   double planes[24];
960   cam->GetFrustumPlanes(ren->GetTiledAspectRatio(), planes);
961 
962   // convert geometry to world then compare to frustum planes
963   double in[4];
964   in[3] = 1.0;
965   double out[4];
966   double worldGeometry[24];
967   for (int i = 0; i < 8; ++i)
968   {
969     in[0] = geometry[i * 3];
970     in[1] = geometry[i * 3 + 1];
971     in[2] = geometry[i * 3 + 2];
972     dataToWorld->MultiplyPoint(in, out);
973     worldGeometry[i * 3] = out[0] / out[3];
974     worldGeometry[i * 3 + 1] = out[1] / out[3];
975     worldGeometry[i * 3 + 2] = out[2] / out[3];
976   }
977 
978   // does the front clipping plane intersect the volume?
979   // true if points are on both sides of the plane
980   bool hasPositive = false;
981   bool hasNegative = false;
982   bool hasZero = false;
983   for (int i = 0; i < 8; ++i)
984   {
985     double val = planes[4 * 4] * worldGeometry[i * 3] +
986       planes[4 * 4 + 1] * worldGeometry[i * 3 + 1] + planes[4 * 4 + 2] * worldGeometry[i * 3 + 2] +
987       planes[4 * 4 + 3];
988     if (val < 0)
989     {
990       hasNegative = true;
991     }
992     else if (val > 0)
993     {
994       hasPositive = true;
995     }
996     else
997     {
998       hasZero = true;
999     }
1000   }
1001 
1002   return hasZero || (hasNegative && hasPositive);
1003 }
1004 
1005 //------------------------------------------------------------------------------
IsGeometryUpdateRequired(vtkRenderer * ren,vtkVolume * vol,double geometry[24])1006 bool vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::IsGeometryUpdateRequired(
1007   vtkRenderer* ren, vtkVolume* vol, double geometry[24])
1008 {
1009   if (!this->BBoxPolyData)
1010   {
1011     return true;
1012   }
1013 
1014   const auto GeomTime = this->BBoxPolyData->GetMTime();
1015   const bool uploadTimeChanged =
1016     any_of(this->Parent->AssembledInputs.begin(), this->Parent->AssembledInputs.end(),
1017       [&GeomTime](const std::pair<int, vtkVolumeInputHelper>& item) {
1018         return item.second.Texture->UploadTime > GeomTime;
1019       });
1020 
1021   return (this->NeedToInitializeResources || uploadTimeChanged ||
1022     this->IsCameraInside(ren, vol, geometry) || this->CameraWasInsideInLastUpdate ||
1023     (this->MultiVolume && this->MultiVolume->GetBoundsTime() > this->BBoxPolyData->GetMTime()));
1024 }
1025 
1026 //------------------------------------------------------------------------------
RenderVolumeGeometry(vtkRenderer * ren,vtkShaderProgram * prog,vtkVolume * vol,double geometry[24])1027 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::RenderVolumeGeometry(
1028   vtkRenderer* ren, vtkShaderProgram* prog, vtkVolume* vol, double geometry[24])
1029 {
1030   if (this->IsGeometryUpdateRequired(ren, vol, geometry))
1031   {
1032     vtkNew<vtkPolyData> boxSource;
1033 
1034     {
1035       vtkNew<vtkCellArray> cells;
1036       vtkNew<vtkPoints> points;
1037       points->SetDataTypeToDouble();
1038       for (int i = 0; i < 8; ++i)
1039       {
1040         points->InsertNextPoint(geometry + i * 3);
1041       }
1042       // 6 faces 12 triangles
1043       int tris[36] = {
1044         0, 1, 2, //
1045         1, 3, 2, //
1046         1, 5, 3, //
1047         5, 7, 3, //
1048         5, 4, 7, //
1049         4, 6, 7, //
1050         4, 0, 6, //
1051         0, 2, 6, //
1052         2, 3, 6, //
1053         3, 7, 6, //
1054         0, 4, 1, //
1055         1, 4, 5  //
1056       };
1057       for (int i = 0; i < 12; ++i)
1058       {
1059         cells->InsertNextCell(3);
1060         // this code uses a clockwise convention for some reason
1061         // no clue why but the ClipConvexPolyData assumes the same
1062         // so we add verts as 0 2 1 instead of 0 1 2
1063         cells->InsertCellPoint(tris[i * 3]);
1064         cells->InsertCellPoint(tris[i * 3 + 2]);
1065         cells->InsertCellPoint(tris[i * 3 + 1]);
1066       }
1067       boxSource->SetPoints(points);
1068       boxSource->SetPolys(cells);
1069     }
1070 
1071     vtkNew<vtkDensifyPolyData> densifyPolyData;
1072     if (this->IsCameraInside(ren, vol, geometry))
1073     {
1074       vtkNew<vtkMatrix4x4> dataToWorld;
1075       dataToWorld->DeepCopy(vol->GetMatrix());
1076 
1077       vtkCamera* cam = ren->GetActiveCamera();
1078 
1079       double fplanes[24];
1080       cam->GetFrustumPlanes(ren->GetTiledAspectRatio(), fplanes);
1081 
1082       // have to convert the 5th plane to volume coordinates
1083       double pOrigin[4];
1084       pOrigin[3] = 1.0;
1085       double pNormal[3];
1086       for (int i = 0; i < 3; ++i)
1087       {
1088         pNormal[i] = fplanes[16 + i];
1089         pOrigin[i] = -fplanes[16 + 3] * fplanes[16 + i];
1090       }
1091 
1092       // convert the normal
1093       double* dmat = dataToWorld->GetData();
1094       dataToWorld->Transpose();
1095       double pNormalV[3];
1096       pNormalV[0] = pNormal[0] * dmat[0] + pNormal[1] * dmat[1] + pNormal[2] * dmat[2];
1097       pNormalV[1] = pNormal[0] * dmat[4] + pNormal[1] * dmat[5] + pNormal[2] * dmat[6];
1098       pNormalV[2] = pNormal[0] * dmat[8] + pNormal[1] * dmat[9] + pNormal[2] * dmat[10];
1099       vtkMath::Normalize(pNormalV);
1100 
1101       // convert the point
1102       dataToWorld->Transpose();
1103       dataToWorld->Invert();
1104       dataToWorld->MultiplyPoint(pOrigin, pOrigin);
1105 
1106       vtkNew<vtkPlane> nearPlane;
1107 
1108       // We add an offset to the near plane to avoid hardware clipping of the
1109       // near plane due to floating-point precision.
1110       // camPlaneNormal is a unit vector, if the offset is larger than the
1111       // distance between near and far point, it will not work. Hence, we choose
1112       // a fraction of the near-far distance. However, care should be taken
1113       // to avoid hardware clipping in volumes with very small spacing where the
1114       // distance between near and far plane is also very small. In that case,
1115       // a minimum offset is chosen. This is chosen based on the typical
1116       // epsilon values on x86 systems.
1117       double offset = (cam->GetClippingRange()[1] - cam->GetClippingRange()[0]) * 0.001;
1118       // Minimum offset to avoid floating point precision issues for volumes
1119       // with very small spacing
1120       double minOffset = static_cast<double>(std::numeric_limits<float>::epsilon()) * 1000.0;
1121       offset = offset < minOffset ? minOffset : offset;
1122 
1123       for (int i = 0; i < 3; ++i)
1124       {
1125         pOrigin[i] += (pNormalV[i] * offset);
1126       }
1127 
1128       nearPlane->SetOrigin(pOrigin);
1129       nearPlane->SetNormal(pNormalV);
1130 
1131       vtkNew<vtkPlaneCollection> planes;
1132       planes->RemoveAllItems();
1133       planes->AddItem(nearPlane);
1134 
1135       vtkNew<vtkClipConvexPolyData> clip;
1136       clip->SetInputData(boxSource);
1137       clip->SetPlanes(planes);
1138 
1139       densifyPolyData->SetInputConnection(clip->GetOutputPort());
1140 
1141       this->CameraWasInsideInLastUpdate = true;
1142     }
1143     else
1144     {
1145       densifyPolyData->SetInputData(boxSource);
1146       this->CameraWasInsideInLastUpdate = false;
1147     }
1148 
1149     densifyPolyData->SetNumberOfSubdivisions(2);
1150     densifyPolyData->Update();
1151 
1152     this->BBoxPolyData = vtkSmartPointer<vtkPolyData>::New();
1153     this->BBoxPolyData->ShallowCopy(densifyPolyData->GetOutput());
1154     vtkPoints* points = this->BBoxPolyData->GetPoints();
1155     vtkCellArray* cells = this->BBoxPolyData->GetPolys();
1156 
1157     vtkNew<vtkUnsignedIntArray> polys;
1158     polys->SetNumberOfComponents(3);
1159     vtkIdType npts;
1160     const vtkIdType* pts;
1161 
1162     // See if the volume transform is orientation-preserving
1163     // and orient polygons accordingly
1164     vtkMatrix4x4* volMat = vol->GetMatrix();
1165     double det = vtkMath::Determinant3x3(volMat->GetElement(0, 0), volMat->GetElement(0, 1),
1166       volMat->GetElement(0, 2), volMat->GetElement(1, 0), volMat->GetElement(1, 1),
1167       volMat->GetElement(1, 2), volMat->GetElement(2, 0), volMat->GetElement(2, 1),
1168       volMat->GetElement(2, 2));
1169     bool preservesOrientation = det > 0.0;
1170 
1171     const vtkIdType indexMap[3] = { preservesOrientation ? 0 : 2, 1, preservesOrientation ? 2 : 0 };
1172 
1173     while (cells->GetNextCell(npts, pts))
1174     {
1175       polys->InsertNextTuple3(pts[indexMap[0]], pts[indexMap[1]], pts[indexMap[2]]);
1176     }
1177 
1178     // Dispose any previously created buffers
1179     this->DeleteBufferObjects();
1180 
1181     // Now create new ones
1182     this->CreateBufferObjects();
1183 
1184     // TODO: should really use the built in VAO class
1185     glBindVertexArray(this->CubeVAOId);
1186 
1187     // Pass cube vertices to buffer object memory
1188     glBindBuffer(GL_ARRAY_BUFFER, this->CubeVBOId);
1189     glBufferData(GL_ARRAY_BUFFER,
1190       points->GetData()->GetDataSize() * points->GetData()->GetDataTypeSize(),
1191       points->GetData()->GetVoidPointer(0), GL_STATIC_DRAW);
1192 
1193     prog->EnableAttributeArray("in_vertexPos");
1194     prog->UseAttributeArray("in_vertexPos", 0, 0, VTK_FLOAT, 3, vtkShaderProgram::NoNormalize);
1195 
1196     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->CubeIndicesId);
1197     glBufferData(GL_ELEMENT_ARRAY_BUFFER, polys->GetDataSize() * polys->GetDataTypeSize(),
1198       polys->GetVoidPointer(0), GL_STATIC_DRAW);
1199   }
1200   else
1201   {
1202     glBindVertexArray(this->CubeVAOId);
1203   }
1204 
1205   glDrawElements(
1206     GL_TRIANGLES, this->BBoxPolyData->GetNumberOfCells() * 3, GL_UNSIGNED_INT, nullptr);
1207 
1208   vtkOpenGLStaticCheckErrorMacro("Error after glDrawElements in"
1209                                  " RenderVolumeGeometry!");
1210   glBindVertexArray(0);
1211   glBindBuffer(GL_ARRAY_BUFFER, 0);
1212   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1213 }
1214 
1215 //------------------------------------------------------------------------------
SetCroppingRegions(vtkShaderProgram * prog,double loadedBounds[6])1216 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetCroppingRegions(
1217   vtkShaderProgram* prog, double loadedBounds[6])
1218 {
1219   if (this->Parent->GetCropping())
1220   {
1221     int cropFlags = this->Parent->GetCroppingRegionFlags();
1222     double croppingRegionPlanes[6];
1223     this->Parent->GetCroppingRegionPlanes(croppingRegionPlanes);
1224 
1225     // Clamp it
1226     croppingRegionPlanes[0] =
1227       croppingRegionPlanes[0] < loadedBounds[0] ? loadedBounds[0] : croppingRegionPlanes[0];
1228     croppingRegionPlanes[0] =
1229       croppingRegionPlanes[0] > loadedBounds[1] ? loadedBounds[1] : croppingRegionPlanes[0];
1230     croppingRegionPlanes[1] =
1231       croppingRegionPlanes[1] < loadedBounds[0] ? loadedBounds[0] : croppingRegionPlanes[1];
1232     croppingRegionPlanes[1] =
1233       croppingRegionPlanes[1] > loadedBounds[1] ? loadedBounds[1] : croppingRegionPlanes[1];
1234 
1235     croppingRegionPlanes[2] =
1236       croppingRegionPlanes[2] < loadedBounds[2] ? loadedBounds[2] : croppingRegionPlanes[2];
1237     croppingRegionPlanes[2] =
1238       croppingRegionPlanes[2] > loadedBounds[3] ? loadedBounds[3] : croppingRegionPlanes[2];
1239     croppingRegionPlanes[3] =
1240       croppingRegionPlanes[3] < loadedBounds[2] ? loadedBounds[2] : croppingRegionPlanes[3];
1241     croppingRegionPlanes[3] =
1242       croppingRegionPlanes[3] > loadedBounds[3] ? loadedBounds[3] : croppingRegionPlanes[3];
1243 
1244     croppingRegionPlanes[4] =
1245       croppingRegionPlanes[4] < loadedBounds[4] ? loadedBounds[4] : croppingRegionPlanes[4];
1246     croppingRegionPlanes[4] =
1247       croppingRegionPlanes[4] > loadedBounds[5] ? loadedBounds[5] : croppingRegionPlanes[4];
1248     croppingRegionPlanes[5] =
1249       croppingRegionPlanes[5] < loadedBounds[4] ? loadedBounds[4] : croppingRegionPlanes[5];
1250     croppingRegionPlanes[5] =
1251       croppingRegionPlanes[5] > loadedBounds[5] ? loadedBounds[5] : croppingRegionPlanes[5];
1252 
1253     float cropPlanes[6] = { static_cast<float>(croppingRegionPlanes[0]),
1254       static_cast<float>(croppingRegionPlanes[1]), static_cast<float>(croppingRegionPlanes[2]),
1255       static_cast<float>(croppingRegionPlanes[3]), static_cast<float>(croppingRegionPlanes[4]),
1256       static_cast<float>(croppingRegionPlanes[5]) };
1257 
1258     prog->SetUniform1fv("in_croppingPlanes", 6, cropPlanes);
1259     const int numberOfRegions = 32;
1260     int cropFlagsArray[numberOfRegions];
1261     cropFlagsArray[0] = 0;
1262     int i = 1;
1263     while (cropFlags && i < 32)
1264     {
1265       cropFlagsArray[i] = cropFlags & 1;
1266       cropFlags = cropFlags >> 1;
1267       ++i;
1268     }
1269     for (; i < 32; ++i)
1270     {
1271       cropFlagsArray[i] = 0;
1272     }
1273 
1274     prog->SetUniform1iv("in_croppingFlags", numberOfRegions, cropFlagsArray);
1275   }
1276 }
1277 
1278 //------------------------------------------------------------------------------
SetClippingPlanes(vtkRenderer * vtkNotUsed (ren),vtkShaderProgram * prog,vtkVolume * vol)1279 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetClippingPlanes(
1280   vtkRenderer* vtkNotUsed(ren), vtkShaderProgram* prog, vtkVolume* vol)
1281 {
1282   if (this->Parent->GetClippingPlanes())
1283   {
1284     std::vector<float> clippingPlanes;
1285     // Currently we don't have any clipping plane
1286     clippingPlanes.push_back(0);
1287 
1288     this->Parent->ClippingPlanes->InitTraversal();
1289     vtkPlane* plane;
1290     while ((plane = this->Parent->ClippingPlanes->GetNextItem()))
1291     {
1292       // Planes are in world coordinates
1293       double planeOrigin[3], planeNormal[3];
1294       plane->GetOrigin(planeOrigin);
1295       plane->GetNormal(planeNormal);
1296 
1297       clippingPlanes.push_back(planeOrigin[0]);
1298       clippingPlanes.push_back(planeOrigin[1]);
1299       clippingPlanes.push_back(planeOrigin[2]);
1300       clippingPlanes.push_back(planeNormal[0]);
1301       clippingPlanes.push_back(planeNormal[1]);
1302       clippingPlanes.push_back(planeNormal[2]);
1303     }
1304 
1305     clippingPlanes[0] = clippingPlanes.size() > 1 ? static_cast<int>(clippingPlanes.size() - 1) : 0;
1306 
1307     prog->SetUniform1fv(
1308       "in_clippingPlanes", static_cast<int>(clippingPlanes.size()), &clippingPlanes[0]);
1309     float clippedVoxelIntensity =
1310       static_cast<float>(vol->GetProperty()->GetClippedVoxelIntensity());
1311     prog->SetUniformf("in_clippedVoxelIntensity", clippedVoxelIntensity);
1312   }
1313 }
1314 
1315 //------------------------------------------------------------------------------
CheckPropertyKeys(vtkVolume * vol)1316 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::CheckPropertyKeys(vtkVolume* vol)
1317 {
1318   // Check the property keys to see if we should modify the blend/etc state:
1319   // Otherwise this breaks volume/translucent geo depth peeling.
1320   vtkInformation* volumeKeys = vol->GetPropertyKeys();
1321   this->PreserveGLState = false;
1322   if (volumeKeys && volumeKeys->Has(vtkOpenGLActor::GLDepthMaskOverride()))
1323   {
1324     int override = volumeKeys->Get(vtkOpenGLActor::GLDepthMaskOverride());
1325     if (override != 0 && override != 1)
1326     {
1327       this->PreserveGLState = true;
1328     }
1329   }
1330 
1331   // Some render passes (e.g. DualDepthPeeling) adjust the viewport for
1332   // intermediate passes so it is necessary to preserve it. This is a
1333   // temporary fix for vtkDualDepthPeelingPass to work when various viewports
1334   // are defined.  The correct way of fixing this would be to avoid setting the
1335   // viewport within the mapper.  It is enough for now to check for the
1336   // RenderPasses() vtkInfo given that vtkDualDepthPeelingPass is the only pass
1337   // currently supported by this mapper, the viewport will have to be adjusted
1338   // externally before adding support for other passes.
1339   vtkInformation* info = vol->GetPropertyKeys();
1340   this->PreserveViewport = info && info->Has(vtkOpenGLRenderPass::RenderPasses());
1341 }
1342 
1343 //------------------------------------------------------------------------------
CheckPickingState(vtkRenderer * ren)1344 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::CheckPickingState(vtkRenderer* ren)
1345 {
1346   vtkHardwareSelector* selector = ren->GetSelector();
1347   bool selectorPicking = selector != nullptr;
1348   if (selector)
1349   {
1350     // this mapper currently only supports cell picking
1351     selectorPicking &= selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_CELLS;
1352   }
1353 
1354   this->IsPicking = selectorPicking;
1355   if (this->IsPicking)
1356   {
1357     // rebuild the shader on every pass
1358     this->SelectionStateTime.Modified();
1359     this->CurrentSelectionPass =
1360       selector ? selector->GetCurrentPass() : vtkHardwareSelector::ACTOR_PASS;
1361   }
1362   else if (this->CurrentSelectionPass != vtkHardwareSelector::MIN_KNOWN_PASS - 1)
1363   {
1364     // return to the regular rendering state
1365     this->SelectionStateTime.Modified();
1366     this->CurrentSelectionPass = vtkHardwareSelector::MIN_KNOWN_PASS - 1;
1367   }
1368 }
1369 
1370 //------------------------------------------------------------------------------
BeginPicking(vtkRenderer * ren)1371 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::BeginPicking(vtkRenderer* ren)
1372 {
1373   vtkHardwareSelector* selector = ren->GetSelector();
1374   if (selector && this->IsPicking)
1375   {
1376     selector->BeginRenderProp();
1377   }
1378 }
1379 
1380 //------------------------------------------------------------------------------
SetPickingId(vtkRenderer * ren)1381 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetPickingId(vtkRenderer* ren)
1382 {
1383   float propIdColor[3] = { 0.0, 0.0, 0.0 };
1384   vtkHardwareSelector* selector = ren->GetSelector();
1385 
1386   if (selector && this->IsPicking)
1387   {
1388     // query the selector for the appropriate id
1389     selector->GetPropColorValue(propIdColor);
1390   }
1391 
1392   this->ShaderProgram->SetUniform3f("in_propId", propIdColor);
1393 }
1394 
1395 //------------------------------------------------------------------------------
EndPicking(vtkRenderer * ren)1396 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::EndPicking(vtkRenderer* ren)
1397 {
1398   vtkHardwareSelector* selector = ren->GetSelector();
1399   if (selector && this->IsPicking)
1400   {
1401     if (this->CurrentSelectionPass >= vtkHardwareSelector::POINT_ID_LOW24)
1402     {
1403       // Only supported on single-input
1404       int extents[6];
1405       auto dataSet = this->Parent->GetTransformedInput(0);
1406       if (auto imData = vtkImageData::SafeDownCast(dataSet))
1407       {
1408         imData->GetExtent(extents);
1409       }
1410       else if (auto rectGrid = vtkRectilinearGrid::SafeDownCast(dataSet))
1411       {
1412         rectGrid->GetExtent(extents);
1413       }
1414 
1415       // Tell the selector the maximum number of cells that the mapper could render
1416       unsigned int const numVoxels = (extents[1] - extents[0] + 1) * (extents[3] - extents[2] + 1) *
1417         (extents[5] - extents[4] + 1);
1418       selector->UpdateMaximumPointId(numVoxels);
1419       selector->UpdateMaximumCellId(numVoxels);
1420     }
1421     selector->EndRenderProp();
1422   }
1423 }
1424 
1425 //------------------------------------------------------------------------------
UpdateSamplingDistance(vtkRenderer * vtkNotUsed (ren))1426 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::UpdateSamplingDistance(
1427   vtkRenderer* vtkNotUsed(ren))
1428 {
1429   auto input = this->Parent->GetTransformedInput(0);
1430   auto imData = vtkImageData::SafeDownCast(input);
1431   auto rectGrid = vtkRectilinearGrid::SafeDownCast(input);
1432   auto vol = this->Parent->AssembledInputs[0].Volume;
1433   double cellSpacing[3];
1434   if (imData)
1435   {
1436     imData->GetSpacing(cellSpacing);
1437   }
1438   else if (rectGrid)
1439   {
1440     double bounds[6];
1441     rectGrid->GetBounds(bounds);
1442     int dims[3];
1443     rectGrid->GetDimensions(dims);
1444     for (int cc = 0; cc < 3; ++cc)
1445     {
1446       cellSpacing[cc] = (bounds[2 * cc + 1] - bounds[2 * cc]) / dims[cc];
1447     }
1448   }
1449 
1450   if (!this->Parent->AutoAdjustSampleDistances)
1451   {
1452     if (this->Parent->LockSampleDistanceToInputSpacing)
1453     {
1454       int extents[6];
1455       if (imData)
1456       {
1457         imData->GetExtent(extents);
1458       }
1459       else if (rectGrid)
1460       {
1461         rectGrid->GetExtent(extents);
1462       }
1463 
1464       float const d =
1465         static_cast<float>(this->Parent->SpacingAdjustedSampleDistance(cellSpacing, extents));
1466       float const sample = this->Parent->SampleDistance;
1467 
1468       // ActualSampleDistance will grow proportionally to numVoxels^(1/3) (see
1469       // vtkVolumeMapper.cxx). Until it reaches 1/2 average voxel size when number of
1470       // voxels is 1E6.
1471       this->ActualSampleDistance =
1472         (sample / d < 0.999f || sample / d > 1.001f) ? d : this->Parent->SampleDistance;
1473 
1474       return;
1475     }
1476 
1477     this->ActualSampleDistance = this->Parent->SampleDistance;
1478   }
1479   else
1480   {
1481     vtkMatrix4x4* worldToDataset = vol->GetMatrix();
1482     double minWorldSpacing = VTK_DOUBLE_MAX;
1483     int i = 0;
1484     while (i < 3)
1485     {
1486       double tmp = worldToDataset->GetElement(0, i);
1487       double tmp2 = tmp * tmp;
1488       tmp = worldToDataset->GetElement(1, i);
1489       tmp2 += tmp * tmp;
1490       tmp = worldToDataset->GetElement(2, i);
1491       tmp2 += tmp * tmp;
1492 
1493       // We use fabs() in case the spacing is negative.
1494       double worldSpacing = fabs(cellSpacing[i] * sqrt(tmp2));
1495       if (worldSpacing < minWorldSpacing)
1496       {
1497         minWorldSpacing = worldSpacing;
1498       }
1499       ++i;
1500     }
1501 
1502     // minWorldSpacing is the optimal sample distance in world space.
1503     // To go faster (reduceFactor<1.0), we multiply this distance
1504     // by 1/reduceFactor.
1505     this->ActualSampleDistance = static_cast<float>(minWorldSpacing);
1506 
1507     if (this->Parent->ReductionFactor < 1.0 && this->Parent->ReductionFactor != 0.0)
1508     {
1509       this->ActualSampleDistance /= static_cast<GLfloat>(this->Parent->ReductionFactor);
1510     }
1511   }
1512 }
1513 
1514 //------------------------------------------------------------------------------
LoadRequireDepthTextureExtensions(vtkRenderWindow * vtkNotUsed (renWin))1515 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::LoadRequireDepthTextureExtensions(
1516   vtkRenderWindow* vtkNotUsed(renWin))
1517 {
1518   // Reset the message stream for extensions
1519   this->LoadDepthTextureExtensionsSucceeded = true;
1520 }
1521 
1522 //------------------------------------------------------------------------------
CreateBufferObjects()1523 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::CreateBufferObjects()
1524 {
1525   glGenVertexArrays(1, &this->CubeVAOId);
1526   glGenBuffers(1, &this->CubeVBOId);
1527   glGenBuffers(1, &this->CubeIndicesId);
1528 }
1529 
1530 //------------------------------------------------------------------------------
DeleteBufferObjects()1531 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::DeleteBufferObjects()
1532 {
1533   if (this->CubeVBOId)
1534   {
1535     glBindBuffer(GL_ARRAY_BUFFER, this->CubeVBOId);
1536     glDeleteBuffers(1, &this->CubeVBOId);
1537     this->CubeVBOId = 0;
1538   }
1539 
1540   if (this->CubeIndicesId)
1541   {
1542     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->CubeIndicesId);
1543     glDeleteBuffers(1, &this->CubeIndicesId);
1544     this->CubeIndicesId = 0;
1545   }
1546 
1547   if (this->CubeVAOId)
1548   {
1549     glDeleteVertexArrays(1, &this->CubeVAOId);
1550     this->CubeVAOId = 0;
1551   }
1552 }
1553 
1554 //------------------------------------------------------------------------------
ConvertTextureToImageData(vtkTextureObject * texture,vtkImageData * output)1555 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ConvertTextureToImageData(
1556   vtkTextureObject* texture, vtkImageData* output)
1557 {
1558   if (!texture)
1559   {
1560     return;
1561   }
1562   unsigned int tw = texture->GetWidth();
1563   unsigned int th = texture->GetHeight();
1564   unsigned int tnc = texture->GetComponents();
1565   int tt = texture->GetVTKDataType();
1566 
1567   vtkPixelExtent texExt(0U, tw - 1U, 0U, th - 1U);
1568 
1569   int dataExt[6] = { 0, 0, 0, 0, 0, 0 };
1570   texExt.GetData(dataExt);
1571 
1572   double dataOrigin[6] = { 0, 0, 0, 0, 0, 0 };
1573 
1574   vtkImageData* id = vtkImageData::New();
1575   id->SetOrigin(dataOrigin);
1576   id->SetDimensions(tw, th, 1);
1577   id->SetExtent(dataExt);
1578   id->AllocateScalars(tt, tnc);
1579 
1580   vtkPixelBufferObject* pbo = texture->Download();
1581 
1582   vtkPixelTransfer::Blit(texExt, texExt, texExt, texExt, tnc, tt, pbo->MapPackedBuffer(), tnc, tt,
1583     id->GetScalarPointer(0, 0, 0));
1584 
1585   pbo->UnmapPackedBuffer();
1586   pbo->Delete();
1587 
1588   if (!output)
1589   {
1590     output = vtkImageData::New();
1591   }
1592   output->DeepCopy(id);
1593   id->Delete();
1594 }
1595 
1596 //------------------------------------------------------------------------------
BeginImageSample(vtkRenderer * ren)1597 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::BeginImageSample(vtkRenderer* ren)
1598 {
1599   auto vol = this->GetActiveVolume();
1600   const auto numBuffers = this->GetNumImageSampleDrawBuffers(vol);
1601   if (numBuffers != this->NumImageSampleDrawBuffers)
1602   {
1603     if (numBuffers > this->NumImageSampleDrawBuffers)
1604     {
1605       this->ReleaseImageSampleGraphicsResources(ren->GetRenderWindow());
1606     }
1607 
1608     this->NumImageSampleDrawBuffers = numBuffers;
1609     this->RebuildImageSampleProg = true;
1610   }
1611 
1612   float const xySampleDist = this->Parent->ImageSampleDistance;
1613   if (xySampleDist != 1.f && this->InitializeImageSampleFBO(ren))
1614   {
1615     this->ImageSampleFBO->GetContext()->GetState()->PushDrawFramebufferBinding();
1616     this->ImageSampleFBO->Bind(GL_DRAW_FRAMEBUFFER);
1617     this->ImageSampleFBO->ActivateDrawBuffers(
1618       static_cast<unsigned int>(this->NumImageSampleDrawBuffers));
1619 
1620     this->ImageSampleFBO->GetContext()->GetState()->vtkglClearColor(0.0, 0.0, 0.0, 0.0);
1621     this->ImageSampleFBO->GetContext()->GetState()->vtkglClear(GL_COLOR_BUFFER_BIT);
1622   }
1623 }
1624 
1625 //------------------------------------------------------------------------------
InitializeImageSampleFBO(vtkRenderer * ren)1626 bool vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::InitializeImageSampleFBO(vtkRenderer* ren)
1627 {
1628   // Set the FBO viewport size. These are used in the shader to normalize the
1629   // fragment coordinate, the normalized coordinate is used to fetch the depth
1630   // buffer.
1631   this->WindowSize[0] /= this->Parent->ImageSampleDistance;
1632   this->WindowSize[1] /= this->Parent->ImageSampleDistance;
1633   this->WindowLowerLeft[0] = 0;
1634   this->WindowLowerLeft[1] = 0;
1635 
1636   vtkOpenGLRenderWindow* win = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
1637 
1638   // Set FBO viewport
1639   win->GetState()->vtkglViewport(
1640     this->WindowLowerLeft[0], this->WindowLowerLeft[1], this->WindowSize[0], this->WindowSize[1]);
1641 
1642   if (!this->ImageSampleFBO)
1643   {
1644     this->ImageSampleTexture.reserve(this->NumImageSampleDrawBuffers);
1645     this->ImageSampleTexNames.reserve(this->NumImageSampleDrawBuffers);
1646     for (size_t i = 0; i < this->NumImageSampleDrawBuffers; i++)
1647     {
1648       auto tex = vtkSmartPointer<vtkTextureObject>::New();
1649       tex->SetContext(win);
1650       tex->Create2D(this->WindowSize[0], this->WindowSize[1], 4, VTK_UNSIGNED_CHAR, false);
1651       tex->Activate();
1652       tex->SetMinificationFilter(vtkTextureObject::Linear);
1653       tex->SetMagnificationFilter(vtkTextureObject::Linear);
1654       tex->SetWrapS(vtkTextureObject::ClampToEdge);
1655       tex->SetWrapT(vtkTextureObject::ClampToEdge);
1656       this->ImageSampleTexture.push_back(tex);
1657 
1658       std::stringstream ss;
1659       ss << i;
1660       const std::string name = "renderedTex_" + ss.str();
1661       this->ImageSampleTexNames.push_back(name);
1662     }
1663 
1664     this->ImageSampleFBO = vtkOpenGLFramebufferObject::New();
1665     this->ImageSampleFBO->SetContext(win);
1666     win->GetState()->PushFramebufferBindings();
1667     this->ImageSampleFBO->Bind();
1668     this->ImageSampleFBO->InitializeViewport(this->WindowSize[0], this->WindowSize[1]);
1669 
1670     auto num = static_cast<unsigned int>(this->NumImageSampleDrawBuffers);
1671     for (unsigned int i = 0; i < num; i++)
1672     {
1673       this->ImageSampleFBO->AddColorAttachment(i, this->ImageSampleTexture[i]);
1674     }
1675 
1676     // Verify completeness
1677     const int complete = this->ImageSampleFBO->CheckFrameBufferStatus(GL_FRAMEBUFFER);
1678     for (auto& tex : this->ImageSampleTexture)
1679     {
1680       tex->Deactivate();
1681     }
1682     win->GetState()->PopFramebufferBindings();
1683 
1684     if (!complete)
1685     {
1686       vtkGenericWarningMacro(<< "Failed to attach ImageSampleFBO!");
1687       this->ReleaseImageSampleGraphicsResources(win);
1688       return false;
1689     }
1690 
1691     this->RebuildImageSampleProg = true;
1692     return true;
1693   }
1694 
1695   // Resize if necessary
1696   int lastSize[2];
1697   this->ImageSampleFBO->GetLastSize(lastSize);
1698   if (lastSize[0] != this->WindowSize[0] || lastSize[1] != this->WindowSize[1])
1699   {
1700     this->ImageSampleFBO->Resize(this->WindowSize[0], this->WindowSize[1]);
1701   }
1702 
1703   return true;
1704 }
1705 
1706 //------------------------------------------------------------------------------
EndImageSample(vtkRenderer * ren)1707 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::EndImageSample(vtkRenderer* ren)
1708 {
1709   if (this->Parent->ImageSampleDistance != 1.f)
1710   {
1711     this->ImageSampleFBO->DeactivateDrawBuffers();
1712     if (this->RenderPassAttached)
1713     {
1714       this->ImageSampleFBO->ActivateDrawBuffers(
1715         static_cast<unsigned int>(this->NumImageSampleDrawBuffers));
1716     }
1717     vtkOpenGLRenderWindow* win = static_cast<vtkOpenGLRenderWindow*>(ren->GetRenderWindow());
1718     win->GetState()->PopDrawFramebufferBinding();
1719 
1720     // Render the contents of ImageSampleFBO as a quad to intermix with the
1721     // rest of the scene.
1722     typedef vtkOpenGLRenderUtilities GLUtil;
1723 
1724     if (this->RebuildImageSampleProg)
1725     {
1726       std::string frag = GLUtil::GetFullScreenQuadFragmentShaderTemplate();
1727 
1728       vtkShaderProgram::Substitute(frag, "//VTK::FSQ::Decl",
1729         vtkvolume::ImageSampleDeclarationFrag(
1730           this->ImageSampleTexNames, this->NumImageSampleDrawBuffers));
1731       vtkShaderProgram::Substitute(frag, "//VTK::FSQ::Impl",
1732         vtkvolume::ImageSampleImplementationFrag(
1733           this->ImageSampleTexNames, this->NumImageSampleDrawBuffers));
1734 
1735       this->ImageSampleProg =
1736         win->GetShaderCache()->ReadyShaderProgram(GLUtil::GetFullScreenQuadVertexShader().c_str(),
1737           frag.c_str(), GLUtil::GetFullScreenQuadGeometryShader().c_str());
1738     }
1739     else
1740     {
1741       win->GetShaderCache()->ReadyShaderProgram(this->ImageSampleProg);
1742     }
1743 
1744     if (!this->ImageSampleProg)
1745     {
1746       vtkGenericWarningMacro(<< "Failed to initialize ImageSampleProgram!");
1747       return;
1748     }
1749 
1750     if (!this->ImageSampleVAO)
1751     {
1752       this->ImageSampleVAO = vtkOpenGLVertexArrayObject::New();
1753       GLUtil::PrepFullScreenVAO(win, this->ImageSampleVAO, this->ImageSampleProg);
1754     }
1755 
1756     vtkOpenGLState* ostate = win->GetState();
1757 
1758     // Adjust the GL viewport to VTK's defined viewport
1759     ren->GetTiledSizeAndOrigin(
1760       this->WindowSize, this->WindowSize + 1, this->WindowLowerLeft, this->WindowLowerLeft + 1);
1761     ostate->vtkglViewport(
1762       this->WindowLowerLeft[0], this->WindowLowerLeft[1], this->WindowSize[0], this->WindowSize[1]);
1763 
1764     // Bind objects and draw
1765     ostate->vtkglEnable(GL_BLEND);
1766     ostate->vtkglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1767     ostate->vtkglDisable(GL_DEPTH_TEST);
1768 
1769     for (size_t i = 0; i < this->NumImageSampleDrawBuffers; i++)
1770     {
1771       this->ImageSampleTexture[i]->Activate();
1772       this->ImageSampleProg->SetUniformi(
1773         this->ImageSampleTexNames[i].c_str(), this->ImageSampleTexture[i]->GetTextureUnit());
1774     }
1775 
1776     this->ImageSampleVAO->Bind();
1777     GLUtil::DrawFullScreenQuad();
1778     this->ImageSampleVAO->Release();
1779     vtkOpenGLStaticCheckErrorMacro("Error after DrawFullScreenQuad()!");
1780 
1781     for (auto& tex : this->ImageSampleTexture)
1782     {
1783       tex->Deactivate();
1784     }
1785   }
1786 }
1787 
1788 //------------------------------------------------------------------------------
GetNumImageSampleDrawBuffers(vtkVolume * vol)1789 size_t vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::GetNumImageSampleDrawBuffers(vtkVolume* vol)
1790 {
1791   if (this->RenderPassAttached)
1792   {
1793     vtkInformation* info = vol->GetPropertyKeys();
1794     const int num = info->Length(vtkOpenGLRenderPass::RenderPasses());
1795     vtkObjectBase* rpBase = info->Get(vtkOpenGLRenderPass::RenderPasses(), num - 1);
1796     vtkOpenGLRenderPass* rp = static_cast<vtkOpenGLRenderPass*>(rpBase);
1797     return static_cast<size_t>(rp->GetActiveDrawBuffers());
1798   }
1799 
1800   return 1;
1801 }
1802 
1803 //------------------------------------------------------------------------------
SetupRenderToTexture(vtkRenderer * ren)1804 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetupRenderToTexture(vtkRenderer* ren)
1805 {
1806   if (this->Parent->RenderToImage && this->Parent->CurrentPass == RenderPass)
1807   {
1808     if (this->Parent->ImageSampleDistance != 1.f)
1809     {
1810       this->WindowSize[0] /= this->Parent->ImageSampleDistance;
1811       this->WindowSize[1] /= this->Parent->ImageSampleDistance;
1812     }
1813 
1814     if ((this->LastRenderToImageWindowSize[0] != this->WindowSize[0]) ||
1815       (this->LastRenderToImageWindowSize[1] != this->WindowSize[1]))
1816     {
1817       this->LastRenderToImageWindowSize[0] = this->WindowSize[0];
1818       this->LastRenderToImageWindowSize[1] = this->WindowSize[1];
1819       this->ReleaseRenderToTextureGraphicsResources(ren->GetRenderWindow());
1820     }
1821 
1822     if (!this->FBO)
1823     {
1824       this->FBO = vtkOpenGLFramebufferObject::New();
1825     }
1826 
1827     vtkOpenGLRenderWindow* renWin = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
1828     this->FBO->SetContext(renWin);
1829 
1830     renWin->GetState()->PushFramebufferBindings();
1831     this->FBO->Bind();
1832     this->FBO->InitializeViewport(this->WindowSize[0], this->WindowSize[1]);
1833 
1834     int depthImageScalarType = this->Parent->GetDepthImageScalarType();
1835     bool initDepthTexture = true;
1836     // Re-instantiate the depth texture object if the scalar type requested has
1837     // changed from the last frame
1838     if (this->RTTDepthTextureObject && this->RTTDepthTextureType == depthImageScalarType)
1839     {
1840       initDepthTexture = false;
1841     }
1842 
1843     if (initDepthTexture)
1844     {
1845       if (this->RTTDepthTextureObject)
1846       {
1847         this->RTTDepthTextureObject->Delete();
1848         this->RTTDepthTextureObject = nullptr;
1849       }
1850       this->RTTDepthTextureObject = vtkTextureObject::New();
1851       this->RTTDepthTextureObject->SetContext(renWin);
1852       this->RTTDepthTextureObject->Create2D(
1853         this->WindowSize[0], this->WindowSize[1], 1, depthImageScalarType, false);
1854       this->RTTDepthTextureObject->Activate();
1855       this->RTTDepthTextureObject->SetMinificationFilter(vtkTextureObject::Nearest);
1856       this->RTTDepthTextureObject->SetMagnificationFilter(vtkTextureObject::Nearest);
1857       this->RTTDepthTextureObject->SetAutoParameters(0);
1858 
1859       // Cache the value of the scalar type
1860       this->RTTDepthTextureType = depthImageScalarType;
1861     }
1862 
1863     if (!this->RTTColorTextureObject)
1864     {
1865       this->RTTColorTextureObject = vtkTextureObject::New();
1866 
1867       this->RTTColorTextureObject->SetContext(
1868         vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow()));
1869       this->RTTColorTextureObject->Create2D(
1870         this->WindowSize[0], this->WindowSize[1], 4, VTK_UNSIGNED_CHAR, false);
1871       this->RTTColorTextureObject->Activate();
1872       this->RTTColorTextureObject->SetMinificationFilter(vtkTextureObject::Nearest);
1873       this->RTTColorTextureObject->SetMagnificationFilter(vtkTextureObject::Nearest);
1874       this->RTTColorTextureObject->SetAutoParameters(0);
1875     }
1876 
1877     if (!this->RTTDepthBufferTextureObject)
1878     {
1879       this->RTTDepthBufferTextureObject = vtkTextureObject::New();
1880       this->RTTDepthBufferTextureObject->SetContext(renWin);
1881       this->RTTDepthBufferTextureObject->AllocateDepth(
1882         this->WindowSize[0], this->WindowSize[1], vtkTextureObject::Float32);
1883       this->RTTDepthBufferTextureObject->Activate();
1884       this->RTTDepthBufferTextureObject->SetMinificationFilter(vtkTextureObject::Nearest);
1885       this->RTTDepthBufferTextureObject->SetMagnificationFilter(vtkTextureObject::Nearest);
1886       this->RTTDepthBufferTextureObject->SetAutoParameters(0);
1887     }
1888 
1889     this->FBO->Bind(GL_FRAMEBUFFER);
1890     this->FBO->AddDepthAttachment(this->RTTDepthBufferTextureObject);
1891     this->FBO->AddColorAttachment(0U, this->RTTColorTextureObject);
1892     this->FBO->AddColorAttachment(1U, this->RTTDepthTextureObject);
1893     this->FBO->ActivateDrawBuffers(2);
1894 
1895     this->FBO->CheckFrameBufferStatus(GL_FRAMEBUFFER);
1896 
1897     this->FBO->GetContext()->GetState()->vtkglClearColor(1.0, 1.0, 1.0, 0.0);
1898     this->FBO->GetContext()->GetState()->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1899   }
1900 }
1901 
1902 //------------------------------------------------------------------------------
ExitRenderToTexture(vtkRenderer * vtkNotUsed (ren))1903 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ExitRenderToTexture(vtkRenderer* vtkNotUsed(ren))
1904 {
1905   if (this->Parent->RenderToImage && this->Parent->CurrentPass == RenderPass)
1906   {
1907     this->FBO->RemoveDepthAttachment();
1908     this->FBO->RemoveColorAttachment(0U);
1909     this->FBO->RemoveColorAttachment(1U);
1910     this->FBO->DeactivateDrawBuffers();
1911     this->FBO->GetContext()->GetState()->PopFramebufferBindings();
1912 
1913     this->RTTDepthBufferTextureObject->Deactivate();
1914     this->RTTColorTextureObject->Deactivate();
1915     this->RTTDepthTextureObject->Deactivate();
1916   }
1917 }
1918 
1919 //------------------------------------------------------------------------------
SetupDepthPass(vtkRenderer * ren)1920 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetupDepthPass(vtkRenderer* ren)
1921 {
1922   if (this->Parent->ImageSampleDistance != 1.f)
1923   {
1924     this->WindowSize[0] /= this->Parent->ImageSampleDistance;
1925     this->WindowSize[1] /= this->Parent->ImageSampleDistance;
1926   }
1927 
1928   if ((this->LastDepthPassWindowSize[0] != this->WindowSize[0]) ||
1929     (this->LastDepthPassWindowSize[1] != this->WindowSize[1]))
1930   {
1931     this->LastDepthPassWindowSize[0] = this->WindowSize[0];
1932     this->LastDepthPassWindowSize[1] = this->WindowSize[1];
1933     this->ReleaseDepthPassGraphicsResources(ren->GetRenderWindow());
1934   }
1935 
1936   if (!this->DPFBO)
1937   {
1938     this->DPFBO = vtkOpenGLFramebufferObject::New();
1939   }
1940 
1941   vtkOpenGLRenderWindow* renWin = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
1942   this->DPFBO->SetContext(renWin);
1943 
1944   renWin->GetState()->PushFramebufferBindings();
1945   this->DPFBO->Bind();
1946   this->DPFBO->InitializeViewport(this->WindowSize[0], this->WindowSize[1]);
1947 
1948   if (!this->DPDepthBufferTextureObject || !this->DPColorTextureObject)
1949   {
1950     this->DPDepthBufferTextureObject = vtkTextureObject::New();
1951     this->DPDepthBufferTextureObject->SetContext(renWin);
1952     this->DPDepthBufferTextureObject->AllocateDepth(
1953       this->WindowSize[0], this->WindowSize[1], vtkTextureObject::Native);
1954     this->DPDepthBufferTextureObject->Activate();
1955     this->DPDepthBufferTextureObject->SetMinificationFilter(vtkTextureObject::Nearest);
1956     this->DPDepthBufferTextureObject->SetMagnificationFilter(vtkTextureObject::Nearest);
1957     this->DPDepthBufferTextureObject->SetAutoParameters(0);
1958     this->DPDepthBufferTextureObject->Bind();
1959 
1960     this->DPColorTextureObject = vtkTextureObject::New();
1961 
1962     this->DPColorTextureObject->SetContext(renWin);
1963     this->DPColorTextureObject->Create2D(
1964       this->WindowSize[0], this->WindowSize[1], 4, VTK_UNSIGNED_CHAR, false);
1965     this->DPColorTextureObject->Activate();
1966     this->DPColorTextureObject->SetMinificationFilter(vtkTextureObject::Nearest);
1967     this->DPColorTextureObject->SetMagnificationFilter(vtkTextureObject::Nearest);
1968     this->DPColorTextureObject->SetAutoParameters(0);
1969 
1970     this->DPFBO->AddDepthAttachment(this->DPDepthBufferTextureObject);
1971 
1972     this->DPFBO->AddColorAttachment(0U, this->DPColorTextureObject);
1973   }
1974 
1975   this->DPFBO->ActivateDrawBuffers(1);
1976   this->DPFBO->CheckFrameBufferStatus(GL_FRAMEBUFFER);
1977 
1978   // Setup the contour polydata mapper to render to DPFBO
1979   this->ContourMapper->SetInputConnection(this->ContourFilter->GetOutputPort());
1980 
1981   vtkOpenGLState* ostate = this->DPFBO->GetContext()->GetState();
1982   ostate->vtkglClearColor(0.0, 0.0, 0.0, 0.0);
1983   ostate->vtkglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1984   ostate->vtkglEnable(GL_DEPTH_TEST);
1985 }
1986 
1987 //------------------------------------------------------------------------------
RenderContourPass(vtkRenderer * ren)1988 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::RenderContourPass(vtkRenderer* ren)
1989 {
1990   this->SetupDepthPass(ren);
1991   this->ContourActor->Render(ren, this->ContourMapper.GetPointer());
1992   this->ExitDepthPass(ren);
1993   this->DepthPassTime.Modified();
1994   this->Parent->CurrentPass = this->Parent->RenderPass;
1995 }
1996 
1997 //------------------------------------------------------------------------------
ExitDepthPass(vtkRenderer * vtkNotUsed (ren))1998 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ExitDepthPass(vtkRenderer* vtkNotUsed(ren))
1999 {
2000   this->DPFBO->DeactivateDrawBuffers();
2001   vtkOpenGLState* ostate = this->DPFBO->GetContext()->GetState();
2002   ostate->PopFramebufferBindings();
2003 
2004   this->DPDepthBufferTextureObject->Deactivate();
2005   this->DPColorTextureObject->Deactivate();
2006   ostate->vtkglDisable(GL_DEPTH_TEST);
2007 }
2008 
2009 //------------------------------------------------------------------------------
ReleaseRenderToTextureGraphicsResources(vtkWindow * win)2010 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal ::ReleaseRenderToTextureGraphicsResources(
2011   vtkWindow* win)
2012 {
2013   vtkOpenGLRenderWindow* rwin = vtkOpenGLRenderWindow::SafeDownCast(win);
2014 
2015   if (rwin)
2016   {
2017     if (this->FBO)
2018     {
2019       this->FBO->Delete();
2020       this->FBO = nullptr;
2021     }
2022 
2023     if (this->RTTDepthBufferTextureObject)
2024     {
2025       this->RTTDepthBufferTextureObject->ReleaseGraphicsResources(win);
2026       this->RTTDepthBufferTextureObject->Delete();
2027       this->RTTDepthBufferTextureObject = nullptr;
2028     }
2029 
2030     if (this->RTTDepthTextureObject)
2031     {
2032       this->RTTDepthTextureObject->ReleaseGraphicsResources(win);
2033       this->RTTDepthTextureObject->Delete();
2034       this->RTTDepthTextureObject = nullptr;
2035     }
2036 
2037     if (this->RTTColorTextureObject)
2038     {
2039       this->RTTColorTextureObject->ReleaseGraphicsResources(win);
2040       this->RTTColorTextureObject->Delete();
2041       this->RTTColorTextureObject = nullptr;
2042     }
2043   }
2044 }
2045 
2046 //------------------------------------------------------------------------------
ReleaseDepthPassGraphicsResources(vtkWindow * win)2047 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal ::ReleaseDepthPassGraphicsResources(
2048   vtkWindow* win)
2049 {
2050   vtkOpenGLRenderWindow* rwin = vtkOpenGLRenderWindow::SafeDownCast(win);
2051 
2052   if (rwin)
2053   {
2054     if (this->DPFBO)
2055     {
2056       this->DPFBO->Delete();
2057       this->DPFBO = nullptr;
2058     }
2059 
2060     if (this->DPDepthBufferTextureObject)
2061     {
2062       this->DPDepthBufferTextureObject->ReleaseGraphicsResources(win);
2063       this->DPDepthBufferTextureObject->Delete();
2064       this->DPDepthBufferTextureObject = nullptr;
2065     }
2066 
2067     if (this->DPColorTextureObject)
2068     {
2069       this->DPColorTextureObject->ReleaseGraphicsResources(win);
2070       this->DPColorTextureObject->Delete();
2071       this->DPColorTextureObject = nullptr;
2072     }
2073 
2074     this->ContourMapper->ReleaseGraphicsResources(win);
2075   }
2076 }
2077 
2078 //------------------------------------------------------------------------------
ReleaseImageSampleGraphicsResources(vtkWindow * win)2079 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal ::ReleaseImageSampleGraphicsResources(
2080   vtkWindow* win)
2081 {
2082   vtkOpenGLRenderWindow* rwin = vtkOpenGLRenderWindow::SafeDownCast(win);
2083 
2084   if (rwin)
2085   {
2086     if (this->ImageSampleFBO)
2087     {
2088       this->ImageSampleFBO->Delete();
2089       this->ImageSampleFBO = nullptr;
2090     }
2091 
2092     for (auto& tex : this->ImageSampleTexture)
2093     {
2094       tex->ReleaseGraphicsResources(win);
2095       tex = nullptr;
2096     }
2097     this->ImageSampleTexture.clear();
2098     this->ImageSampleTexNames.clear();
2099 
2100     if (this->ImageSampleVAO)
2101     {
2102       this->ImageSampleVAO->Delete();
2103       this->ImageSampleVAO = nullptr;
2104     }
2105 
2106     // Do not delete the shader program - Let the cache clean it up.
2107     this->ImageSampleProg = nullptr;
2108   }
2109 }
2110 
2111 //------------------------------------------------------------------------------
vtkOpenGLGPUVolumeRayCastMapper()2112 vtkOpenGLGPUVolumeRayCastMapper::vtkOpenGLGPUVolumeRayCastMapper()
2113 {
2114   this->Impl = new vtkInternal(this);
2115   this->ReductionFactor = 1.0;
2116   this->CurrentPass = RenderPass;
2117 
2118   this->ResourceCallback = new vtkOpenGLResourceFreeCallback<vtkOpenGLGPUVolumeRayCastMapper>(
2119     this, &vtkOpenGLGPUVolumeRayCastMapper::ReleaseGraphicsResources);
2120 
2121   //  this->VolumeTexture = vtkVolumeTexture::New();
2122   //  this->VolumeTexture->SetMapper(this);
2123 }
2124 
2125 //------------------------------------------------------------------------------
~vtkOpenGLGPUVolumeRayCastMapper()2126 vtkOpenGLGPUVolumeRayCastMapper::~vtkOpenGLGPUVolumeRayCastMapper()
2127 {
2128   if (this->ResourceCallback)
2129   {
2130     this->ResourceCallback->Release();
2131     delete this->ResourceCallback;
2132     this->ResourceCallback = nullptr;
2133   }
2134 
2135   delete this->Impl;
2136   this->Impl = nullptr;
2137 
2138   this->AssembledInputs.clear();
2139 }
2140 
2141 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)2142 void vtkOpenGLGPUVolumeRayCastMapper::PrintSelf(ostream& os, vtkIndent indent)
2143 {
2144   this->Superclass::PrintSelf(os, indent);
2145 
2146   os << indent << "ReductionFactor: " << this->ReductionFactor << "\n";
2147   os << indent << "CurrentPass: " << this->CurrentPass << "\n";
2148 }
2149 
SetSharedDepthTexture(vtkTextureObject * nt)2150 void vtkOpenGLGPUVolumeRayCastMapper::SetSharedDepthTexture(vtkTextureObject* nt)
2151 {
2152   if (this->Impl->DepthTextureObject == nt)
2153   {
2154     return;
2155   }
2156   if (this->Impl->DepthTextureObject)
2157   {
2158     this->Impl->DepthTextureObject->Delete();
2159   }
2160   this->Impl->DepthTextureObject = nt;
2161 
2162   if (nt)
2163   {
2164     nt->Register(this); // as it will get deleted later on
2165     this->Impl->SharedDepthTextureObject = true;
2166   }
2167   else
2168   {
2169     this->Impl->SharedDepthTextureObject = false;
2170   }
2171 }
2172 
2173 //------------------------------------------------------------------------------
GetDepthTexture()2174 vtkTextureObject* vtkOpenGLGPUVolumeRayCastMapper::GetDepthTexture()
2175 {
2176   return this->Impl->RTTDepthTextureObject;
2177 }
2178 
2179 //------------------------------------------------------------------------------
GetColorTexture()2180 vtkTextureObject* vtkOpenGLGPUVolumeRayCastMapper::GetColorTexture()
2181 {
2182   return this->Impl->RTTColorTextureObject;
2183 }
2184 
2185 //------------------------------------------------------------------------------
GetDepthImage(vtkImageData * output)2186 void vtkOpenGLGPUVolumeRayCastMapper::GetDepthImage(vtkImageData* output)
2187 {
2188   return this->Impl->ConvertTextureToImageData(this->Impl->RTTDepthTextureObject, output);
2189 }
2190 
2191 //------------------------------------------------------------------------------
GetColorImage(vtkImageData * output)2192 void vtkOpenGLGPUVolumeRayCastMapper::GetColorImage(vtkImageData* output)
2193 {
2194   return this->Impl->ConvertTextureToImageData(this->Impl->RTTColorTextureObject, output);
2195 }
2196 
2197 //------------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * window)2198 void vtkOpenGLGPUVolumeRayCastMapper::ReleaseGraphicsResources(vtkWindow* window)
2199 {
2200   if (!this->ResourceCallback->IsReleasing())
2201   {
2202     this->ResourceCallback->Release();
2203     return;
2204   }
2205 
2206   this->Impl->DeleteBufferObjects();
2207 
2208   for (auto& input : this->AssembledInputs)
2209   {
2210     input.second.ReleaseGraphicsResources(window);
2211   }
2212 
2213   if (this->Impl->DepthTextureObject && !this->Impl->SharedDepthTextureObject)
2214   {
2215     this->Impl->DepthTextureObject->ReleaseGraphicsResources(window);
2216     this->Impl->DepthTextureObject->Delete();
2217     this->Impl->DepthTextureObject = nullptr;
2218     this->Impl->DepthCopyColorTextureObject->ReleaseGraphicsResources(window);
2219     this->Impl->DepthCopyColorTextureObject->Delete();
2220     this->Impl->DepthCopyColorTextureObject = nullptr;
2221     this->Impl->DepthCopyFBO->ReleaseGraphicsResources(window);
2222     this->Impl->DepthCopyFBO->Delete();
2223     this->Impl->DepthCopyFBO = nullptr;
2224   }
2225 
2226   this->Impl->ReleaseRenderToTextureGraphicsResources(window);
2227   this->Impl->ReleaseDepthPassGraphicsResources(window);
2228   this->Impl->ReleaseImageSampleGraphicsResources(window);
2229 
2230   if (this->Impl->CurrentMask)
2231   {
2232     this->Impl->CurrentMask->ReleaseGraphicsResources(window);
2233     this->Impl->CurrentMask = nullptr;
2234   }
2235 
2236   this->Impl->ReleaseGraphicsMaskTransfer(window);
2237   this->Impl->DeleteMaskTransfer();
2238 
2239   this->Impl->ReleaseResourcesTime.Modified();
2240 }
2241 
2242 //------------------------------------------------------------------------------
GetShaderTemplate(std::map<vtkShader::Type,vtkShader * > & shaders,vtkOpenGLShaderProperty * p)2243 void vtkOpenGLGPUVolumeRayCastMapper::GetShaderTemplate(
2244   std::map<vtkShader::Type, vtkShader*>& shaders, vtkOpenGLShaderProperty* p)
2245 {
2246   if (shaders[vtkShader::Vertex])
2247   {
2248     if (p->HasVertexShaderCode())
2249     {
2250       shaders[vtkShader::Vertex]->SetSource(p->GetVertexShaderCode());
2251     }
2252     else
2253     {
2254       shaders[vtkShader::Vertex]->SetSource(raycastervs);
2255     }
2256   }
2257 
2258   if (shaders[vtkShader::Fragment])
2259   {
2260     if (p->HasFragmentShaderCode())
2261     {
2262       shaders[vtkShader::Fragment]->SetSource(p->GetFragmentShaderCode());
2263     }
2264     else
2265     {
2266       shaders[vtkShader::Fragment]->SetSource(raycasterfs);
2267     }
2268   }
2269 
2270   if (shaders[vtkShader::Geometry])
2271   {
2272     shaders[vtkShader::Geometry]->SetSource("");
2273   }
2274 }
2275 
2276 //------------------------------------------------------------------------------
ReplaceShaderCustomUniforms(std::map<vtkShader::Type,vtkShader * > & shaders,vtkOpenGLShaderProperty * p)2277 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderCustomUniforms(
2278   std::map<vtkShader::Type, vtkShader*>& shaders, vtkOpenGLShaderProperty* p)
2279 {
2280   vtkShader* vertexShader = shaders[vtkShader::Vertex];
2281   vtkOpenGLUniforms* vu = static_cast<vtkOpenGLUniforms*>(p->GetVertexCustomUniforms());
2282   vtkShaderProgram::Substitute(vertexShader, "//VTK::CustomUniforms::Dec", vu->GetDeclarations());
2283 
2284   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2285   vtkOpenGLUniforms* fu = static_cast<vtkOpenGLUniforms*>(p->GetFragmentCustomUniforms());
2286   vtkShaderProgram::Substitute(fragmentShader, "//VTK::CustomUniforms::Dec", fu->GetDeclarations());
2287 
2288   vtkShader* geometryShader = shaders[vtkShader::Geometry];
2289   vtkOpenGLUniforms* gu = static_cast<vtkOpenGLUniforms*>(p->GetGeometryCustomUniforms());
2290   vtkShaderProgram::Substitute(geometryShader, "//VTK::CustomUniforms::Dec", gu->GetDeclarations());
2291 }
2292 
2293 //------------------------------------------------------------------------------
ReplaceShaderBase(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int numComps)2294 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderBase(
2295   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol, int numComps)
2296 {
2297   vtkShader* vertexShader = shaders[vtkShader::Vertex];
2298   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2299 
2300   // Every volume should have a property (cannot be nullptr);
2301   vtkVolumeProperty* volumeProperty = vol->GetProperty();
2302   int independentComponents = volumeProperty->GetIndependentComponents();
2303 
2304   vtkShaderProgram::Substitute(vertexShader, "//VTK::ComputeClipPos::Impl",
2305     vtkvolume::ComputeClipPositionImplementation(ren, this, vol));
2306 
2307   vtkShaderProgram::Substitute(vertexShader, "//VTK::ComputeTextureCoords::Impl",
2308     vtkvolume::ComputeTextureCoordinates(ren, this, vol));
2309 
2310   vtkShaderProgram::Substitute(vertexShader, "//VTK::Base::Dec",
2311     vtkvolume::BaseDeclarationVertex(ren, this, vol, this->Impl->MultiVolume != nullptr));
2312 
2313   vtkShaderProgram::Substitute(
2314     fragmentShader, "//VTK::CallWorker::Impl", vtkvolume::WorkerImplementation(ren, this, vol));
2315 
2316   vtkShaderProgram::Substitute(fragmentShader, "//VTK::Base::Dec",
2317     vtkvolume::BaseDeclarationFragment(ren, this, this->AssembledInputs, this->Impl->NumberOfLights,
2318       this->Impl->LightComplexity, numComps, independentComponents));
2319 
2320   vtkShaderProgram::Substitute(fragmentShader, "//VTK::Base::Init",
2321     vtkvolume::BaseInit(ren, this, this->AssembledInputs, this->Impl->LightComplexity));
2322 
2323   vtkShaderProgram::Substitute(
2324     fragmentShader, "//VTK::Base::Impl", vtkvolume::BaseImplementation(ren, this, vol));
2325 
2326   vtkShaderProgram::Substitute(
2327     fragmentShader, "//VTK::Base::Exit", vtkvolume::BaseExit(ren, this, vol));
2328 }
2329 
2330 //------------------------------------------------------------------------------
ReplaceShaderTermination(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int vtkNotUsed (numComps))2331 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderTermination(
2332   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol,
2333   int vtkNotUsed(numComps))
2334 {
2335   vtkShader* vertexShader = shaders[vtkShader::Vertex];
2336   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2337 
2338   vtkShaderProgram::Substitute(vertexShader, "//VTK::Termination::Dec",
2339     vtkvolume::TerminationDeclarationVertex(ren, this, vol));
2340 
2341   vtkShaderProgram::Substitute(fragmentShader, "//VTK::Termination::Dec",
2342     vtkvolume::TerminationDeclarationFragment(ren, this, vol));
2343 
2344   vtkShaderProgram::Substitute(
2345     fragmentShader, "//VTK::Terminate::Init", vtkvolume::TerminationInit(ren, this, vol));
2346 
2347   vtkShaderProgram::Substitute(
2348     fragmentShader, "//VTK::Terminate::Impl", vtkvolume::TerminationImplementation(ren, this, vol));
2349 
2350   vtkShaderProgram::Substitute(
2351     fragmentShader, "//VTK::Terminate::Exit", vtkvolume::TerminationExit(ren, this, vol));
2352 }
2353 
2354 //------------------------------------------------------------------------------
ReplaceShaderShading(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int numComps)2355 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderShading(
2356   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol, int numComps)
2357 {
2358   vtkShader* vertexShader = shaders[vtkShader::Vertex];
2359   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2360 
2361   // Every volume should have a property (cannot be nullptr);
2362   vtkVolumeProperty* volumeProperty = vol->GetProperty();
2363   int independentComponents = volumeProperty->GetIndependentComponents();
2364 
2365   vtkShaderProgram::Substitute(
2366     vertexShader, "//VTK::Shading::Dec", vtkvolume::ShadingDeclarationVertex(ren, this, vol));
2367 
2368   vtkShaderProgram::Substitute(
2369     fragmentShader, "//VTK::Shading::Dec", vtkvolume::ShadingDeclarationFragment(ren, this, vol));
2370 
2371   vtkShaderProgram::Substitute(
2372     fragmentShader, "//VTK::Shading::Init", vtkvolume::ShadingInit(ren, this, vol));
2373 
2374   if (this->Impl->MultiVolume)
2375   {
2376     vtkShaderProgram::Substitute(fragmentShader, "//VTK::Shading::Impl",
2377       vtkvolume::ShadingMultipleInputs(this, this->AssembledInputs));
2378   }
2379   else
2380   {
2381     vtkShaderProgram::Substitute(fragmentShader, "//VTK::Shading::Impl",
2382       vtkvolume::ShadingSingleInput(ren, this, vol, this->MaskInput, this->Impl->CurrentMask,
2383         this->MaskType, numComps, independentComponents));
2384   }
2385 
2386   vtkShaderProgram::Substitute(fragmentShader, "//VTK::Shading::Exit",
2387     vtkvolume::ShadingExit(ren, this, vol, numComps, independentComponents));
2388 }
2389 
2390 //------------------------------------------------------------------------------
ReplaceShaderCompute(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int numComps)2391 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderCompute(
2392   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol, int numComps)
2393 {
2394   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2395 
2396   // Every volume should have a property (cannot be nullptr);
2397   vtkVolumeProperty* volumeProperty = vol->GetProperty();
2398   int independentComponents = volumeProperty->GetIndependentComponents();
2399 
2400   vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeGradient::Dec",
2401     vtkvolume::ComputeGradientDeclaration(this, this->AssembledInputs));
2402 
2403   if (this->Impl->MultiVolume)
2404   {
2405     vtkShaderProgram::Substitute(fragmentShader, "//VTK::GradientCache::Dec",
2406       vtkvolume::GradientCacheDec(ren, vol, this->AssembledInputs, independentComponents));
2407 
2408     vtkShaderProgram::Substitute(fragmentShader, "//VTK::Transfer2D::Dec",
2409       vtkvolume::Transfer2DDeclaration(this->AssembledInputs));
2410 
2411     vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeOpacity::Dec",
2412       vtkvolume::ComputeOpacityMultiDeclaration(this->AssembledInputs));
2413 
2414     vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeGradientOpacity1D::Dec",
2415       vtkvolume::ComputeGradientOpacityMulti1DDecl(this->AssembledInputs));
2416 
2417     vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeColor::Dec",
2418       vtkvolume::ComputeColorMultiDeclaration(this->AssembledInputs));
2419 
2420     vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeLighting::Dec",
2421       vtkvolume::ComputeLightingMultiDeclaration(ren, this, vol, numComps, independentComponents,
2422         this->Impl->NumberOfLights, this->Impl->LightComplexity));
2423   }
2424   else
2425   {
2426     // Single input
2427     switch (volumeProperty->GetTransferFunctionMode())
2428     {
2429       case vtkVolumeProperty::TF_1D:
2430       {
2431         auto& input = this->AssembledInputs[0];
2432 
2433         vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeOpacity::Dec",
2434           vtkvolume::ComputeOpacityDeclaration(
2435             ren, this, vol, numComps, independentComponents, input.OpacityTablesMap));
2436 
2437         vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeGradientOpacity1D::Dec",
2438           vtkvolume::ComputeGradientOpacity1DDecl(
2439             vol, numComps, independentComponents, input.GradientOpacityTablesMap));
2440 
2441         vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeColor::Dec",
2442           vtkvolume::ComputeColorDeclaration(
2443             ren, this, vol, numComps, independentComponents, input.RGBTablesMap));
2444       }
2445       break;
2446       case vtkVolumeProperty::TF_2D:
2447         vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeOpacity::Dec",
2448           vtkvolume::ComputeOpacity2DDeclaration(ren, this, vol, numComps, independentComponents,
2449             this->AssembledInputs[0].TransferFunctions2DMap, this->Impl->Transfer2DUseGradient));
2450 
2451         vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeColor::Dec",
2452           vtkvolume::ComputeColor2DDeclaration(ren, this, vol, numComps, independentComponents,
2453             this->AssembledInputs[0].TransferFunctions2DMap, this->Impl->Transfer2DUseGradient));
2454 
2455         vtkShaderProgram::Substitute(fragmentShader, "//VTK::GradientCache::Dec",
2456           vtkvolume::GradientCacheDec(ren, vol, this->AssembledInputs, independentComponents));
2457 
2458         vtkShaderProgram::Substitute(fragmentShader, "//VTK::PreComputeGradients::Impl",
2459           vtkvolume::PreComputeGradientsImpl(ren, vol, numComps, independentComponents));
2460 
2461         vtkShaderProgram::Substitute(fragmentShader, "//VTK::Transfer2D::Dec",
2462           vtkvolume::Transfer2DDeclaration(this->AssembledInputs));
2463         break;
2464     }
2465 
2466     vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeLighting::Dec",
2467       vtkvolume::ComputeLightingDeclaration(ren, this, vol, numComps, independentComponents,
2468         this->Impl->NumberOfLights, this->Impl->LightComplexity));
2469   }
2470 
2471   vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeRayDirection::Dec",
2472     vtkvolume::ComputeRayDirectionDeclaration(ren, this, vol, numComps));
2473 }
2474 
2475 //------------------------------------------------------------------------------
ReplaceShaderCropping(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int vtkNotUsed (numComps))2476 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderCropping(
2477   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol,
2478   int vtkNotUsed(numComps))
2479 {
2480   vtkShader* vertexShader = shaders[vtkShader::Vertex];
2481   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2482 
2483   vtkShaderProgram::Substitute(
2484     vertexShader, "//VTK::Cropping::Dec", vtkvolume::CroppingDeclarationVertex(ren, this, vol));
2485 
2486   vtkShaderProgram::Substitute(
2487     fragmentShader, "//VTK::Cropping::Dec", vtkvolume::CroppingDeclarationFragment(ren, this, vol));
2488 
2489   vtkShaderProgram::Substitute(
2490     fragmentShader, "//VTK::Cropping::Init", vtkvolume::CroppingInit(ren, this, vol));
2491 
2492   vtkShaderProgram::Substitute(
2493     fragmentShader, "//VTK::Cropping::Impl", vtkvolume::CroppingImplementation(ren, this, vol));
2494   // true);
2495 
2496   vtkShaderProgram::Substitute(
2497     fragmentShader, "//VTK::Cropping::Exit", vtkvolume::CroppingExit(ren, this, vol));
2498 }
2499 
2500 //------------------------------------------------------------------------------
ReplaceShaderClipping(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int vtkNotUsed (numComps))2501 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderClipping(
2502   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol,
2503   int vtkNotUsed(numComps))
2504 {
2505   vtkShader* vertexShader = shaders[vtkShader::Vertex];
2506   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2507 
2508   vtkShaderProgram::Substitute(
2509     vertexShader, "//VTK::Clipping::Dec", vtkvolume::ClippingDeclarationVertex(ren, this, vol));
2510 
2511   vtkShaderProgram::Substitute(
2512     fragmentShader, "//VTK::Clipping::Dec", vtkvolume::ClippingDeclarationFragment(ren, this, vol));
2513 
2514   vtkShaderProgram::Substitute(
2515     fragmentShader, "//VTK::Clipping::Init", vtkvolume::ClippingInit(ren, this, vol));
2516 
2517   vtkShaderProgram::Substitute(
2518     fragmentShader, "//VTK::Clipping::Impl", vtkvolume::ClippingImplementation(ren, this, vol));
2519 
2520   vtkShaderProgram::Substitute(
2521     fragmentShader, "//VTK::Clipping::Exit", vtkvolume::ClippingExit(ren, this, vol));
2522 }
2523 
2524 //------------------------------------------------------------------------------
ReplaceShaderMasking(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int numComps)2525 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderMasking(
2526   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol, int numComps)
2527 {
2528   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2529 
2530   vtkShaderProgram::Substitute(fragmentShader, "//VTK::BinaryMask::Dec",
2531     vtkvolume::BinaryMaskDeclaration(
2532       ren, this, vol, this->MaskInput, this->Impl->CurrentMask, this->MaskType));
2533 
2534   vtkShaderProgram::Substitute(fragmentShader, "//VTK::BinaryMask::Impl",
2535     vtkvolume::BinaryMaskImplementation(
2536       ren, this, vol, this->MaskInput, this->Impl->CurrentMask, this->MaskType));
2537 
2538   vtkShaderProgram::Substitute(fragmentShader, "//VTK::CompositeMask::Dec",
2539     vtkvolume::CompositeMaskDeclarationFragment(
2540       ren, this, vol, this->MaskInput, this->Impl->CurrentMask, this->MaskType));
2541 
2542   vtkShaderProgram::Substitute(fragmentShader, "//VTK::CompositeMask::Impl",
2543     vtkvolume::CompositeMaskImplementation(
2544       ren, this, vol, this->MaskInput, this->Impl->CurrentMask, this->MaskType, numComps));
2545 }
2546 
2547 //------------------------------------------------------------------------------
ReplaceShaderPicking(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int vtkNotUsed (numComps))2548 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderPicking(
2549   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol,
2550   int vtkNotUsed(numComps))
2551 {
2552   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2553 
2554   if (this->Impl->CurrentSelectionPass != (vtkHardwareSelector::MIN_KNOWN_PASS - 1))
2555   {
2556     switch (this->Impl->CurrentSelectionPass)
2557     {
2558       case vtkHardwareSelector::CELL_ID_LOW24:
2559         vtkShaderProgram::Substitute(fragmentShader, "//VTK::Picking::Exit",
2560           vtkvolume::PickingIdLow24PassExit(ren, this, vol));
2561         break;
2562       case vtkHardwareSelector::CELL_ID_HIGH24:
2563         vtkShaderProgram::Substitute(fragmentShader, "//VTK::Picking::Exit",
2564           vtkvolume::PickingIdHigh24PassExit(ren, this, vol));
2565         break;
2566       default: // ACTOR_PASS, PROCESS_PASS
2567         vtkShaderProgram::Substitute(fragmentShader, "//VTK::Picking::Dec",
2568           vtkvolume::PickingActorPassDeclaration(ren, this, vol));
2569 
2570         vtkShaderProgram::Substitute(
2571           fragmentShader, "//VTK::Picking::Exit", vtkvolume::PickingActorPassExit(ren, this, vol));
2572         break;
2573     }
2574   }
2575 }
2576 
2577 //------------------------------------------------------------------------------
ReplaceShaderRTT(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int vtkNotUsed (numComps))2578 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderRTT(
2579   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol,
2580   int vtkNotUsed(numComps))
2581 {
2582   vtkShader* fragmentShader = shaders[vtkShader::Fragment];
2583 
2584   if (this->RenderToImage)
2585   {
2586     vtkShaderProgram::Substitute(fragmentShader, "//VTK::RenderToImage::Dec",
2587       vtkvolume::RenderToImageDeclarationFragment(ren, this, vol));
2588 
2589     vtkShaderProgram::Substitute(
2590       fragmentShader, "//VTK::RenderToImage::Init", vtkvolume::RenderToImageInit(ren, this, vol));
2591 
2592     vtkShaderProgram::Substitute(fragmentShader, "//VTK::RenderToImage::Impl",
2593       vtkvolume::RenderToImageImplementation(ren, this, vol));
2594 
2595     vtkShaderProgram::Substitute(
2596       fragmentShader, "//VTK::RenderToImage::Exit", vtkvolume::RenderToImageExit(ren, this, vol));
2597   }
2598 }
2599 
2600 //------------------------------------------------------------------------------
ReplaceShaderValues(std::map<vtkShader::Type,vtkShader * > & shaders,vtkRenderer * ren,vtkVolume * vol,int noOfComponents)2601 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderValues(
2602   std::map<vtkShader::Type, vtkShader*>& shaders, vtkRenderer* ren, vtkVolume* vol,
2603   int noOfComponents)
2604 {
2605   // Every volume should have a property (cannot be nullptr);
2606   vtkVolumeProperty* volumeProperty = vol->GetProperty();
2607   auto shaderProperty = vtkOpenGLShaderProperty::SafeDownCast(vol->GetShaderProperty());
2608 
2609   if (volumeProperty->GetShade())
2610   {
2611     vtkLightCollection* lc = ren->GetLights();
2612     vtkLight* light;
2613     this->Impl->NumberOfLights = 0;
2614 
2615     // Compute light complexity.
2616     vtkCollectionSimpleIterator sit;
2617     for (lc->InitTraversal(sit); (light = lc->GetNextLight(sit));)
2618     {
2619       float status = light->GetSwitch();
2620       if (status > 0.0)
2621       {
2622         this->Impl->NumberOfLights++;
2623         if (this->Impl->LightComplexity == 0)
2624         {
2625           this->Impl->LightComplexity = 1;
2626         }
2627       }
2628 
2629       if (this->Impl->LightComplexity == 1 &&
2630         (this->Impl->NumberOfLights > 1 || light->GetIntensity() != 1.0 ||
2631           light->GetLightType() != VTK_LIGHT_TYPE_HEADLIGHT))
2632       {
2633         this->Impl->LightComplexity = 2;
2634       }
2635 
2636       if (this->Impl->LightComplexity < 3 && (light->GetPositional()))
2637       {
2638         this->Impl->LightComplexity = 3;
2639         break;
2640       }
2641     }
2642   }
2643 
2644   // Render pass pre replacements
2645   //---------------------------------------------------------------------------
2646   this->ReplaceShaderRenderPass(shaders, vol, true);
2647 
2648   // Custom uniform variables replacements
2649   //---------------------------------------------------------------------------
2650   this->ReplaceShaderCustomUniforms(shaders, shaderProperty);
2651 
2652   // Base methods replacements
2653   //---------------------------------------------------------------------------
2654   this->ReplaceShaderBase(shaders, ren, vol, noOfComponents);
2655 
2656   // Termination methods replacements
2657   //---------------------------------------------------------------------------
2658   this->ReplaceShaderTermination(shaders, ren, vol, noOfComponents);
2659 
2660   // Shading methods replacements
2661   //---------------------------------------------------------------------------
2662   this->ReplaceShaderShading(shaders, ren, vol, noOfComponents);
2663 
2664   // Compute methods replacements
2665   //---------------------------------------------------------------------------
2666   this->ReplaceShaderCompute(shaders, ren, vol, noOfComponents);
2667 
2668   // Cropping methods replacements
2669   //---------------------------------------------------------------------------
2670   this->ReplaceShaderCropping(shaders, ren, vol, noOfComponents);
2671 
2672   // Clipping methods replacements
2673   //---------------------------------------------------------------------------
2674   this->ReplaceShaderClipping(shaders, ren, vol, noOfComponents);
2675 
2676   // Masking methods replacements
2677   //---------------------------------------------------------------------------
2678   this->ReplaceShaderMasking(shaders, ren, vol, noOfComponents);
2679 
2680   // Picking replacements
2681   //---------------------------------------------------------------------------
2682   this->ReplaceShaderPicking(shaders, ren, vol, noOfComponents);
2683 
2684   // Render to texture
2685   //---------------------------------------------------------------------------
2686   this->ReplaceShaderRTT(shaders, ren, vol, noOfComponents);
2687 
2688   // Set number of isosurfaces
2689   if (this->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND)
2690   {
2691     std::ostringstream ss;
2692     ss << volumeProperty->GetIsoSurfaceValues()->GetNumberOfContours();
2693     vtkShaderProgram::Substitute(shaders[vtkShader::Fragment], "NUMBER_OF_CONTOURS", ss.str());
2694   }
2695 
2696   // Render pass post replacements
2697   //---------------------------------------------------------------------------
2698   this->ReplaceShaderRenderPass(shaders, vol, false);
2699 }
2700 
2701 //------------------------------------------------------------------------------
BuildShader(vtkRenderer * ren)2702 void vtkOpenGLGPUVolumeRayCastMapper::BuildShader(vtkRenderer* ren)
2703 {
2704   std::map<vtkShader::Type, vtkShader*> shaders;
2705   vtkShader* vertexShader = vtkShader::New();
2706   vertexShader->SetType(vtkShader::Vertex);
2707   shaders[vtkShader::Vertex] = vertexShader;
2708   vtkShader* fragmentShader = vtkShader::New();
2709   fragmentShader->SetType(vtkShader::Fragment);
2710   shaders[vtkShader::Fragment] = fragmentShader;
2711   vtkShader* geometryShader = vtkShader::New();
2712   geometryShader->SetType(vtkShader::Geometry);
2713   shaders[vtkShader::Geometry] = geometryShader;
2714 
2715   auto vol = this->Impl->GetActiveVolume();
2716 
2717   vtkOpenGLShaderProperty* sp = vtkOpenGLShaderProperty::SafeDownCast(vol->GetShaderProperty());
2718   this->GetShaderTemplate(shaders, sp);
2719 
2720   // user specified pre replacements
2721   vtkOpenGLShaderProperty::ReplacementMap repMap = sp->GetAllShaderReplacements();
2722   for (const auto& i : repMap)
2723   {
2724     if (i.first.ReplaceFirst)
2725     {
2726       std::string ssrc = shaders[i.first.ShaderType]->GetSource();
2727       vtkShaderProgram::Substitute(
2728         ssrc, i.first.OriginalValue, i.second.Replacement, i.second.ReplaceAll);
2729       shaders[i.first.ShaderType]->SetSource(ssrc);
2730     }
2731   }
2732 
2733   auto numComp = this->AssembledInputs[0].Texture->GetLoadedScalars()->GetNumberOfComponents();
2734   this->ReplaceShaderValues(shaders, ren, vol, numComp);
2735 
2736   // user specified post replacements
2737   for (const auto& i : repMap)
2738   {
2739     if (!i.first.ReplaceFirst)
2740     {
2741       std::string ssrc = shaders[i.first.ShaderType]->GetSource();
2742       vtkShaderProgram::Substitute(
2743         ssrc, i.first.OriginalValue, i.second.Replacement, i.second.ReplaceAll);
2744       shaders[i.first.ShaderType]->SetSource(ssrc);
2745     }
2746   }
2747 
2748   // Now compile the shader
2749   //--------------------------------------------------------------------------
2750   this->Impl->ShaderProgram = this->Impl->ShaderCache->ReadyShaderProgram(shaders);
2751   if (!this->Impl->ShaderProgram || !this->Impl->ShaderProgram->GetCompiled())
2752   {
2753     vtkErrorMacro("Shader failed to compile");
2754   }
2755 
2756   vertexShader->Delete();
2757   fragmentShader->Delete();
2758   geometryShader->Delete();
2759 
2760   this->Impl->ShaderBuildTime.Modified();
2761 }
2762 
2763 //------------------------------------------------------------------------------
2764 // Update the reduction factor of the render viewport (this->ReductionFactor)
2765 // according to the time spent in seconds to render the previous frame
2766 // (this->TimeToDraw) and a time in seconds allocated to render the next
2767 // frame (allocatedTime).
2768 // \pre valid_current_reduction_range: this->ReductionFactor>0.0 &&
2769 // this->ReductionFactor<=1.0 \pre positive_TimeToDraw: this->TimeToDraw>=0.0
2770 // \pre positive_time: allocatedTime>0.0
2771 // \post valid_new_reduction_range: this->ReductionFactor>0.0 &&
2772 // this->ReductionFactor<=1.0
2773 //------------------------------------------------------------------------------
ComputeReductionFactor(double allocatedTime)2774 void vtkOpenGLGPUVolumeRayCastMapper::ComputeReductionFactor(double allocatedTime)
2775 {
2776   if (!this->AutoAdjustSampleDistances)
2777   {
2778     this->ReductionFactor = 1.0 / this->ImageSampleDistance;
2779     return;
2780   }
2781 
2782   if (this->TimeToDraw)
2783   {
2784     double oldFactor = this->ReductionFactor;
2785 
2786     double timeToDraw;
2787     if (allocatedTime < 1.0)
2788     {
2789       timeToDraw = this->SmallTimeToDraw;
2790       if (timeToDraw == 0.0)
2791       {
2792         timeToDraw = this->BigTimeToDraw / 3.0;
2793       }
2794     }
2795     else
2796     {
2797       timeToDraw = this->BigTimeToDraw;
2798     }
2799 
2800     // This should be the case when rendering the volume very first time
2801     // 10.0 is an arbitrary value chosen which happen to a large number
2802     // in this context
2803     if (timeToDraw == 0.0)
2804     {
2805       timeToDraw = 10.0;
2806     }
2807 
2808     double fullTime = timeToDraw / this->ReductionFactor;
2809     double newFactor = allocatedTime / fullTime;
2810 
2811     // Compute average factor
2812     this->ReductionFactor = (newFactor + oldFactor) / 2.0;
2813 
2814     // Discretize reduction factor so that it doesn't cause
2815     // visual artifacts when used to reduce the sample distance
2816     this->ReductionFactor = (this->ReductionFactor > 1.0) ? 1.0 : (this->ReductionFactor);
2817 
2818     if (this->ReductionFactor < 0.20)
2819     {
2820       this->ReductionFactor = 0.10;
2821     }
2822     else if (this->ReductionFactor < 0.50)
2823     {
2824       this->ReductionFactor = 0.20;
2825     }
2826     else if (this->ReductionFactor < 1.0)
2827     {
2828       this->ReductionFactor = 0.50;
2829     }
2830 
2831     // Clamp it
2832     if (1.0 / this->ReductionFactor > this->MaximumImageSampleDistance)
2833     {
2834       this->ReductionFactor = 1.0 / this->MaximumImageSampleDistance;
2835     }
2836     if (1.0 / this->ReductionFactor < this->MinimumImageSampleDistance)
2837     {
2838       this->ReductionFactor = 1.0 / this->MinimumImageSampleDistance;
2839     }
2840   }
2841 }
2842 
2843 //------------------------------------------------------------------------------
PreLoadData(vtkRenderer * ren,vtkVolume * vol)2844 bool vtkOpenGLGPUVolumeRayCastMapper::PreLoadData(vtkRenderer* ren, vtkVolume* vol)
2845 {
2846   if (!this->ValidateRender(ren, vol))
2847   {
2848     return false;
2849   }
2850 
2851   // have to register if we preload
2852   this->ResourceCallback->RegisterGraphicsResources(
2853     static_cast<vtkOpenGLRenderWindow*>(ren->GetVTKWindow()));
2854 
2855   this->Impl->ClearRemovedInputs(ren->GetRenderWindow());
2856   return this->Impl->UpdateInputs(ren, vol);
2857 }
2858 
2859 //------------------------------------------------------------------------------
ForceTransferInit()2860 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ForceTransferInit()
2861 {
2862   auto& inputs = this->Parent->AssembledInputs;
2863   auto fu = [](std::pair<const int, vtkVolumeInputHelper>& p) { p.second.ForceTransferInit(); };
2864   std::for_each(inputs.begin(), inputs.end(), fu);
2865 }
2866 
2867 //------------------------------------------------------------------------------
ClearRemovedInputs(vtkWindow * win)2868 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ClearRemovedInputs(vtkWindow* win)
2869 {
2870   bool orderChanged = false;
2871   for (const int& port : this->Parent->RemovedPorts)
2872   {
2873     auto it = this->Parent->AssembledInputs.find(port);
2874     if (it == this->Parent->AssembledInputs.cend())
2875     {
2876       continue;
2877     }
2878 
2879     auto input = (*it).second;
2880     if (input.Texture)
2881     {
2882       input.Texture->ReleaseGraphicsResources(win);
2883     }
2884     if (input.GradientOpacityTables)
2885     {
2886       input.GradientOpacityTables->ReleaseGraphicsResources(win);
2887     }
2888     if (input.OpacityTables)
2889     {
2890       input.OpacityTables->ReleaseGraphicsResources(win);
2891     }
2892     if (input.RGBTables)
2893     {
2894       input.RGBTables->ReleaseGraphicsResources(win);
2895     }
2896     this->Parent->AssembledInputs.erase(it);
2897     orderChanged = true;
2898   }
2899   this->Parent->RemovedPorts.clear();
2900 
2901   if (orderChanged)
2902   {
2903     this->ForceTransferInit();
2904   }
2905 }
2906 
2907 //------------------------------------------------------------------------------
UpdateInputs(vtkRenderer * ren,vtkVolume * vol)2908 bool vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::UpdateInputs(vtkRenderer* ren, vtkVolume* vol)
2909 {
2910   this->VolumePropertyChanged = false;
2911   bool orderChanged = false;
2912   bool success = true;
2913   for (const auto& port : this->Parent->Ports)
2914   {
2915     if (this->MultiVolume)
2916     {
2917       vol = this->MultiVolume->GetVolume(port);
2918     }
2919     auto property = vol->GetProperty();
2920     auto input = this->Parent->GetTransformedInput(port);
2921 
2922     // Check for property changes
2923     this->VolumePropertyChanged |= property->GetMTime() > this->ShaderBuildTime.GetMTime();
2924 
2925     auto it = this->Parent->AssembledInputs.find(port);
2926     if (it == this->Parent->AssembledInputs.cend() || it->second.Volume != vol)
2927     {
2928       // Create new input structure
2929       auto texture = vtkSmartPointer<vtkVolumeTexture>::New();
2930 
2931       VolumeInput currentInput(texture, vol);
2932       this->Parent->AssembledInputs[port] = std::move(currentInput);
2933       orderChanged = true;
2934 
2935       it = this->Parent->AssembledInputs.find(port);
2936     }
2937     assert(it != this->Parent->AssembledInputs.cend());
2938 
2939     /// TODO Currently, only input arrays with the same name/id/mode can be
2940     // (across input objects) can be rendered. This could be addressed by
2941     // overriding the mapper's settings with array settings defined in the
2942     // vtkMultiVolume instance.
2943     vtkDataArray* scalars = vtkOpenGLGPUVolumeRayCastMapper::GetScalars(input,
2944       this->Parent->ScalarMode, this->Parent->ArrayAccessMode, this->Parent->ArrayId,
2945       this->Parent->ArrayName, this->Parent->CellFlag);
2946 
2947     if (this->NeedToInitializeResources || (input->GetMTime() > it->second.Texture->UploadTime) ||
2948       (scalars != it->second.Texture->GetLoadedScalars()) ||
2949       (scalars != nullptr && scalars->GetMTime() > it->second.Texture->UploadTime))
2950     {
2951       auto& volInput = this->Parent->AssembledInputs[port];
2952       auto volumeTex = volInput.Texture.GetPointer();
2953       volumeTex->SetPartitions(this->Partitions[0], this->Partitions[1], this->Partitions[2]);
2954       success &= volumeTex->LoadVolume(
2955         ren, input, scalars, this->Parent->CellFlag, property->GetInterpolationType());
2956       volInput.ComponentMode = this->GetComponentMode(property, scalars);
2957     }
2958     else
2959     {
2960       // Update vtkVolumeTexture
2961       it->second.Texture->UpdateVolume(property);
2962     }
2963 
2964     // Volume may have changed, so make sure the helper updates its reference to it.
2965     it->second.Volume = vol;
2966   }
2967 
2968   if (orderChanged)
2969   {
2970     this->ForceTransferInit();
2971   }
2972 
2973   return success;
2974 }
2975 
2976 //----------------------------------------------------------------------------
UpdateTransfer2DYAxisArray(vtkRenderer * ren,vtkVolume * vol)2977 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::UpdateTransfer2DYAxisArray(
2978   vtkRenderer* ren, vtkVolume* vol)
2979 {
2980   vtkVolumeProperty* prop = vol->GetProperty();
2981   vtkImageData* input = vtkImageData::SafeDownCast(this->Parent->GetTransformedInput(0));
2982   if (prop->GetTransferFunctionMode() != vtkVolumeProperty::TF_2D)
2983   {
2984     this->Transfer2DUseGradient = true;
2985     return;
2986   }
2987 
2988   bool hasTransfer2DYAxisArray = this->Parent->GetTransfer2DYAxisArray() != nullptr;
2989   bool isCellData = hasTransfer2DYAxisArray &&
2990     input->GetCellData()->HasArray(this->Parent->GetTransfer2DYAxisArray());
2991   bool isPointData = hasTransfer2DYAxisArray &&
2992     input->GetPointData()->HasArray(this->Parent->GetTransfer2DYAxisArray());
2993   hasTransfer2DYAxisArray = hasTransfer2DYAxisArray && (isCellData || isPointData);
2994   if (!hasTransfer2DYAxisArray)
2995   {
2996     this->Transfer2DUseGradient = true;
2997     return;
2998   }
2999   else
3000   {
3001     this->Transfer2DUseGradient = false;
3002   }
3003 
3004   // Now load the array
3005   if (!this->Transfer2DYAxisScalars)
3006   {
3007     this->Transfer2DYAxisScalars = vtkSmartPointer<vtkVolumeTexture>::New();
3008 
3009     const auto part = this->Partitions;
3010     this->Transfer2DYAxisScalars->SetPartitions(part[0], part[1], part[2]);
3011   }
3012   vtkDataArray* arr = nullptr;
3013   if (isPointData)
3014   {
3015     arr = input->GetPointData()->GetArray(this->Parent->GetTransfer2DYAxisArray());
3016   }
3017   else
3018   {
3019     arr = input->GetCellData()->GetArray(this->Parent->GetTransfer2DYAxisArray());
3020   }
3021 
3022   if (input->GetMTime() > this->Transfer2DYAxisScalarsUpdateTime ||
3023     this->Transfer2DYAxisScalars->GetLoadedScalars() != arr ||
3024     (arr && arr->GetMTime() > this->Transfer2DYAxisScalarsUpdateTime))
3025   {
3026     this->Transfer2DYAxisScalars->LoadVolume(
3027       ren, input, arr, isCellData, prop->GetInterpolationType());
3028     this->Transfer2DYAxisScalarsUpdateTime.Modified();
3029   }
3030 }
3031 
3032 //----------------------------------------------------------------------------
GetComponentMode(vtkVolumeProperty * prop,vtkDataArray * array) const3033 int vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::GetComponentMode(
3034   vtkVolumeProperty* prop, vtkDataArray* array) const
3035 {
3036   if (prop->GetIndependentComponents())
3037   {
3038     return VolumeInput::INDEPENDENT;
3039   }
3040   else
3041   {
3042     const auto numComp = array->GetNumberOfComponents();
3043     if (numComp == 1 || numComp == 2)
3044       return VolumeInput::LA;
3045     else if (numComp == 4)
3046       return VolumeInput::RGBA;
3047     else if (numComp == 3)
3048     {
3049       vtkGenericWarningMacro(<< "3 dependent components (e.g. RGB) are not supported."
3050                                 "Only 2 (LA) and 4 (RGBA) supported.");
3051       return VolumeInput::INVALID;
3052     }
3053     else
3054       return VolumeInput::INVALID;
3055   }
3056 }
3057 
3058 //------------------------------------------------------------------------------
GPURender(vtkRenderer * ren,vtkVolume * vol)3059 void vtkOpenGLGPUVolumeRayCastMapper::GPURender(vtkRenderer* ren, vtkVolume* vol)
3060 {
3061   vtkOpenGLClearErrorMacro();
3062 
3063   vtkOpenGLCamera* cam = vtkOpenGLCamera::SafeDownCast(ren->GetActiveCamera());
3064 
3065   if (this->GetBlendMode() == vtkVolumeMapper::ISOSURFACE_BLEND &&
3066     vol->GetProperty()->GetIsoSurfaceValues()->GetNumberOfContours() == 0)
3067   {
3068     // Early exit: nothing to render.
3069     return;
3070   }
3071 
3072   vtkOpenGLRenderWindow* renWin = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
3073   this->ResourceCallback->RegisterGraphicsResources(static_cast<vtkOpenGLRenderWindow*>(renWin));
3074   // Make sure the context is current
3075   renWin->MakeCurrent();
3076 
3077   // Get window size and corners
3078   this->Impl->CheckPropertyKeys(vol);
3079   if (!this->Impl->PreserveViewport)
3080   {
3081     ren->GetTiledSizeAndOrigin(this->Impl->WindowSize, this->Impl->WindowSize + 1,
3082       this->Impl->WindowLowerLeft, this->Impl->WindowLowerLeft + 1);
3083   }
3084   else
3085   {
3086     int vp[4];
3087     glGetIntegerv(GL_VIEWPORT, vp);
3088     this->Impl->WindowLowerLeft[0] = vp[0];
3089     this->Impl->WindowLowerLeft[1] = vp[1];
3090     this->Impl->WindowSize[0] = vp[2];
3091     this->Impl->WindowSize[1] = vp[3];
3092   }
3093 
3094   this->Impl->NeedToInitializeResources =
3095     (this->Impl->ReleaseResourcesTime.GetMTime() > this->Impl->InitializationTime.GetMTime());
3096 
3097   this->ComputeReductionFactor(vol->GetAllocatedRenderTime());
3098   if (!this->Impl->SharedDepthTextureObject)
3099   {
3100     this->Impl->CaptureDepthTexture(ren);
3101   }
3102 
3103   vtkMTimeType renderPassTime = this->GetRenderPassStageMTime(vol);
3104 
3105   const auto multiVol = vtkMultiVolume::SafeDownCast(vol);
3106   this->Impl->MultiVolume = multiVol && this->GetInputCount() > 1 ? multiVol : nullptr;
3107 
3108   this->Impl->ClearRemovedInputs(renWin);
3109   this->Impl->UpdateInputs(ren, vol);
3110   this->Impl->UpdateSamplingDistance(ren);
3111   this->Impl->UpdateTransfer2DYAxisArray(ren, vol);
3112   this->Impl->UpdateTransferFunctions(ren);
3113 
3114   // Masks are only supported on single-input rendering.
3115   if (!this->Impl->MultiVolume)
3116   {
3117     this->Impl->LoadMask(ren);
3118   }
3119 
3120   // Get the shader cache. This is important to make sure that shader cache
3121   // knows the state of various shader programs in use.
3122   this->Impl->ShaderCache =
3123     vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow())->GetShaderCache();
3124 
3125   this->Impl->CheckPickingState(ren);
3126 
3127   if (this->UseDepthPass && this->GetBlendMode() == vtkVolumeMapper::COMPOSITE_BLEND)
3128   {
3129     this->Impl->RenderWithDepthPass(ren, cam, renderPassTime);
3130   }
3131   else
3132   {
3133     if (this->Impl->IsPicking && !this->Impl->MultiVolume)
3134     {
3135       this->Impl->BeginPicking(ren);
3136     }
3137     vtkVolumeStateRAII glState(renWin->GetState(), this->Impl->PreserveGLState);
3138 
3139     if (this->Impl->ShaderRebuildNeeded(cam, vol, renderPassTime))
3140     {
3141       this->Impl->LastProjectionParallel = cam->GetParallelProjection();
3142       this->BuildShader(ren);
3143     }
3144     else
3145     {
3146       // Bind the shader
3147       this->Impl->ShaderCache->ReadyShaderProgram(this->Impl->ShaderProgram);
3148       this->InvokeEvent(vtkCommand::UpdateShaderEvent, this->Impl->ShaderProgram);
3149     }
3150 
3151     vtkOpenGLShaderProperty* shaderProperty =
3152       vtkOpenGLShaderProperty::SafeDownCast(vol->GetShaderProperty());
3153     if (this->RenderToImage)
3154     {
3155       this->Impl->SetupRenderToTexture(ren);
3156       this->Impl->SetRenderToImageParameters(this->Impl->ShaderProgram);
3157       this->DoGPURender(ren, cam, this->Impl->ShaderProgram, shaderProperty);
3158       this->Impl->ExitRenderToTexture(ren);
3159     }
3160     else
3161     {
3162       this->Impl->BeginImageSample(ren);
3163       this->DoGPURender(ren, cam, this->Impl->ShaderProgram, shaderProperty);
3164       this->Impl->EndImageSample(ren);
3165     }
3166 
3167     if (this->Impl->IsPicking && !this->Impl->MultiVolume)
3168     {
3169       this->Impl->EndPicking(ren);
3170     }
3171   }
3172 
3173   glFinish();
3174 }
3175 
3176 //------------------------------------------------------------------------------
ShaderRebuildNeeded(vtkCamera * cam,vtkVolume * vol,vtkMTimeType renderPassTime)3177 bool vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::ShaderRebuildNeeded(
3178   vtkCamera* cam, vtkVolume* vol, vtkMTimeType renderPassTime)
3179 {
3180   return (this->NeedToInitializeResources || this->VolumePropertyChanged ||
3181     vol->GetShaderProperty()->GetShaderMTime() > this->ShaderBuildTime.GetMTime() ||
3182     this->Parent->GetMTime() > this->ShaderBuildTime.GetMTime() ||
3183     cam->GetParallelProjection() != this->LastProjectionParallel ||
3184     this->SelectionStateTime.GetMTime() > this->ShaderBuildTime.GetMTime() ||
3185     renderPassTime > this->ShaderBuildTime);
3186 }
3187 
3188 //------------------------------------------------------------------------------
RenderWithDepthPass(vtkRenderer * ren,vtkOpenGLCamera * cam,vtkMTimeType renderPassTime)3189 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::RenderWithDepthPass(
3190   vtkRenderer* ren, vtkOpenGLCamera* cam, vtkMTimeType renderPassTime)
3191 {
3192   this->Parent->CurrentPass = DepthPass;
3193   auto& input = this->Parent->AssembledInputs[0];
3194   auto vol = input.Volume;
3195   auto volumeProperty = vol->GetProperty();
3196   auto shaderProperty = vtkOpenGLShaderProperty::SafeDownCast(vol->GetShaderProperty());
3197 
3198   if (this->NeedToInitializeResources ||
3199     volumeProperty->GetMTime() > this->DepthPassSetupTime.GetMTime() ||
3200     this->Parent->GetMTime() > this->DepthPassSetupTime.GetMTime() ||
3201     cam->GetParallelProjection() != this->LastProjectionParallel ||
3202     this->SelectionStateTime.GetMTime() > this->ShaderBuildTime.GetMTime() ||
3203     renderPassTime > this->ShaderBuildTime ||
3204     shaderProperty->GetShaderMTime() > this->ShaderBuildTime)
3205   {
3206     this->LastProjectionParallel = cam->GetParallelProjection();
3207 
3208     this->ContourFilter->SetInputData(this->Parent->GetTransformedInput(0));
3209     for (vtkIdType i = 0; i < this->Parent->GetDepthPassContourValues()->GetNumberOfContours(); ++i)
3210     {
3211       this->ContourFilter->SetValue(i, this->Parent->DepthPassContourValues->GetValue(i));
3212     }
3213 
3214     this->RenderContourPass(ren);
3215     this->DepthPassSetupTime.Modified();
3216     this->Parent->BuildShader(ren);
3217   }
3218   else if (cam->GetMTime() > this->DepthPassTime.GetMTime())
3219   {
3220     this->RenderContourPass(ren);
3221   }
3222 
3223   if (this->IsPicking)
3224   {
3225     this->BeginPicking(ren);
3226   }
3227 
3228   // Set OpenGL states
3229   vtkOpenGLRenderWindow* renWin = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow());
3230   vtkVolumeStateRAII glState(renWin->GetState(), this->PreserveGLState);
3231 
3232   if (this->Parent->RenderToImage)
3233   {
3234     this->SetupRenderToTexture(ren);
3235   }
3236 
3237   if (!this->PreserveViewport)
3238   {
3239     // NOTE: This is a must call or else, multiple viewport rendering would
3240     // not work. The glViewport could have been changed by any of the internal
3241     // FBOs (RenderToTexure, etc.).  The viewport should (ideally) not be set
3242     // within the mapper, because it could cause issues when vtkOpenGLRenderPass
3243     // instances modify it too (this is a workaround for that).
3244     renWin->GetState()->vtkglViewport(
3245       this->WindowLowerLeft[0], this->WindowLowerLeft[1], this->WindowSize[0], this->WindowSize[1]);
3246   }
3247 
3248   renWin->GetShaderCache()->ReadyShaderProgram(this->ShaderProgram);
3249   this->Parent->InvokeEvent(vtkCommand::UpdateShaderEvent, this->ShaderProgram);
3250 
3251   this->DPDepthBufferTextureObject->Activate();
3252   this->ShaderProgram->SetUniformi(
3253     "in_depthPassSampler", this->DPDepthBufferTextureObject->GetTextureUnit());
3254   this->Parent->DoGPURender(ren, cam, this->ShaderProgram, shaderProperty);
3255   this->DPDepthBufferTextureObject->Deactivate();
3256 
3257   if (this->IsPicking)
3258   {
3259     this->EndPicking(ren);
3260   }
3261 }
3262 
3263 //------------------------------------------------------------------------------
BindTransformations(vtkShaderProgram * prog,vtkMatrix4x4 * modelViewMat)3264 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::BindTransformations(
3265   vtkShaderProgram* prog, vtkMatrix4x4* modelViewMat)
3266 {
3267   // Bind transformations. Because the bounding box has its own transformations,
3268   // it is considered here as an actual volume (numInputs + 1).
3269   const int numInputs = static_cast<int>(this->Parent->AssembledInputs.size());
3270   const int numVolumes = this->MultiVolume ? numInputs + 1 : numInputs;
3271 
3272   this->VolMatVec.resize(numVolumes * 16, 0);
3273   this->InvMatVec.resize(numVolumes * 16, 0);
3274   this->TexMatVec.resize(numVolumes * 16, 0);
3275   this->InvTexMatVec.resize(numVolumes * 16, 0);
3276   this->TexEyeMatVec.resize(numVolumes * 16, 0);
3277   this->CellToPointVec.resize(numVolumes * 16, 0);
3278   this->TexMinVec.resize(numVolumes * 3, 0);
3279   this->TexMaxVec.resize(numVolumes * 3, 0);
3280 
3281   vtkNew<vtkMatrix4x4> dataToWorld, texToDataMat, texToViewMat, cellToPointMat;
3282   float defaultTexMin[3] = { 0.f, 0.f, 0.f };
3283   float defaultTexMax[3] = { 1.f, 1.f, 1.f };
3284 
3285   auto it = this->Parent->AssembledInputs.begin();
3286   for (int i = 0; i < numVolumes; i++)
3287   {
3288     const int vecOffset = i * 16;
3289     float *texMin, *texMax;
3290 
3291     if (this->MultiVolume && i == 0)
3292     {
3293       // Bounding box
3294       auto bBoxToWorld = this->MultiVolume->GetMatrix();
3295       dataToWorld->DeepCopy(bBoxToWorld);
3296 
3297       auto texToBBox = this->MultiVolume->GetTextureMatrix();
3298       texToDataMat->DeepCopy(texToBBox);
3299 
3300       cellToPointMat->Identity();
3301       texMin = defaultTexMin;
3302       texMax = defaultTexMax;
3303     }
3304     else
3305     {
3306       // Volume inputs
3307       auto& inputData = (*it).second;
3308       it++;
3309       auto volTex = inputData.Texture;
3310       auto volMatrix = inputData.Volume->GetMatrix();
3311       dataToWorld->DeepCopy(volMatrix);
3312       texToDataMat->DeepCopy(volTex->GetCurrentBlock()->TextureToDataset.GetPointer());
3313 
3314       // Texture matrices (texture to view)
3315       vtkMatrix4x4::Multiply4x4(volMatrix, texToDataMat.GetPointer(), texToViewMat.GetPointer());
3316       vtkMatrix4x4::Multiply4x4(modelViewMat, texToViewMat.GetPointer(), texToViewMat.GetPointer());
3317 
3318       // texToViewMat->Transpose();
3319       vtkInternal::CopyMatrixToVector<vtkMatrix4x4, 4, 4>(
3320         texToViewMat.GetPointer(), this->TexEyeMatVec.data(), vecOffset);
3321 
3322       // Cell to Point (texture-cells to texture-points)
3323       cellToPointMat->DeepCopy(volTex->CellToPointMatrix.GetPointer());
3324       texMin = volTex->AdjustedTexMin;
3325       texMax = volTex->AdjustedTexMax;
3326       if (volTex->CoordsTex)
3327       {
3328         volTex->CoordsTex->Activate();
3329         prog->SetUniformi("in_coordTexs", volTex->CoordsTex->GetTextureUnit());
3330         float fvalue3[3];
3331         vtkInternal::ToFloat(volTex->CoordsTexSizes, fvalue3, 3);
3332         prog->SetUniform3fv("in_coordTexSizes", 1, &fvalue3);
3333         prog->SetUniform3fv("in_coordsScale", 1, volTex->CoordsScale);
3334         prog->SetUniform3fv("in_coordsBias", 1, volTex->CoordsBias);
3335       }
3336 
3337       if (volTex->BlankingTex)
3338       {
3339         volTex->BlankingTex->Activate();
3340         prog->SetUniformi("in_blanking", volTex->BlankingTex->GetTextureUnit());
3341       }
3342     }
3343 
3344     // Volume matrices (dataset to world)
3345     dataToWorld->Transpose();
3346     vtkInternal::CopyMatrixToVector<vtkMatrix4x4, 4, 4>(
3347       dataToWorld.GetPointer(), this->VolMatVec.data(), vecOffset);
3348 
3349     this->InverseVolumeMat->DeepCopy(dataToWorld.GetPointer());
3350     this->InverseVolumeMat->Invert();
3351     vtkInternal::CopyMatrixToVector<vtkMatrix4x4, 4, 4>(
3352       this->InverseVolumeMat.GetPointer(), this->InvMatVec.data(), vecOffset);
3353 
3354     // Texture matrices (texture to dataset)
3355     texToDataMat->Transpose();
3356     vtkInternal::CopyMatrixToVector<vtkMatrix4x4, 4, 4>(
3357       texToDataMat.GetPointer(), this->TexMatVec.data(), vecOffset);
3358 
3359     texToDataMat->Invert();
3360     vtkInternal::CopyMatrixToVector<vtkMatrix4x4, 4, 4>(
3361       texToDataMat.GetPointer(), this->InvTexMatVec.data(), vecOffset);
3362 
3363     // Cell to Point (texture adjustment)
3364     cellToPointMat->Transpose();
3365     vtkInternal::CopyMatrixToVector<vtkMatrix4x4, 4, 4>(
3366       cellToPointMat.GetPointer(), this->CellToPointVec.data(), vecOffset);
3367     vtkInternal::CopyVector<float, 3>(texMin, this->TexMinVec.data(), i * 3);
3368     vtkInternal::CopyVector<float, 3>(texMax, this->TexMaxVec.data(), i * 3);
3369   }
3370 
3371   // the matrix from data to world
3372   prog->SetUniformMatrix4x4v("in_volumeMatrix", numVolumes, this->VolMatVec.data());
3373   prog->SetUniformMatrix4x4v("in_inverseVolumeMatrix", numVolumes, this->InvMatVec.data());
3374 
3375   // the matrix from tcoords to data
3376   prog->SetUniformMatrix4x4v("in_textureDatasetMatrix", numVolumes, this->TexMatVec.data());
3377   prog->SetUniformMatrix4x4v(
3378     "in_inverseTextureDatasetMatrix", numVolumes, this->InvTexMatVec.data());
3379 
3380   // matrix from texture to view coordinates
3381   prog->SetUniformMatrix4x4v("in_textureToEye", numVolumes, this->TexEyeMatVec.data());
3382 
3383   // handle cell/point differences in tcoords
3384   prog->SetUniformMatrix4x4v("in_cellToPoint", numVolumes, this->CellToPointVec.data());
3385 
3386   prog->SetUniform3fv(
3387     "in_texMin", numVolumes, reinterpret_cast<const float(*)[3]>(this->TexMinVec.data()));
3388   prog->SetUniform3fv(
3389     "in_texMax", numVolumes, reinterpret_cast<const float(*)[3]>(this->TexMaxVec.data()));
3390 }
3391 
3392 //------------------------------------------------------------------------------
SetVolumeShaderParameters(vtkShaderProgram * prog,int independentComponents,int noOfComponents,vtkMatrix4x4 * modelViewMat)3393 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetVolumeShaderParameters(
3394   vtkShaderProgram* prog, int independentComponents, int noOfComponents, vtkMatrix4x4* modelViewMat)
3395 {
3396   this->BindTransformations(prog, modelViewMat);
3397 
3398   // Bind other properties (per-input)
3399   const int numInputs = static_cast<int>(this->Parent->AssembledInputs.size());
3400   this->ScaleVec.resize(numInputs * 4, 0);
3401   this->BiasVec.resize(numInputs * 4, 0);
3402   this->StepVec.resize(numInputs * 3, 0);
3403   this->SpacingVec.resize(numInputs * 3, 0);
3404   this->RangeVec.resize(numInputs * 8, 0);
3405 
3406   int index = 0;
3407   for (auto& input : this->Parent->AssembledInputs)
3408   {
3409     // Bind volume textures
3410     auto block = input.second.Texture->GetCurrentBlock();
3411     std::stringstream ss;
3412     ss << "in_volume[" << index << "]";
3413     block->TextureObject->Activate();
3414     prog->SetUniformi(ss.str().c_str(), block->TextureObject->GetTextureUnit());
3415 
3416     // LargeDataTypes have been already biased and scaled so in those cases 0s
3417     // and 1s are passed respectively.
3418     float tscale[4] = { 1.0, 1.0, 1.0, 1.0 };
3419     float tbias[4] = { 0.0, 0.0, 0.0, 0.0 };
3420     float(*scalePtr)[4] = &tscale;
3421     float(*biasPtr)[4] = &tbias;
3422     auto volTex = input.second.Texture.GetPointer();
3423     if (!volTex->HandleLargeDataTypes &&
3424       (noOfComponents == 1 || noOfComponents == 2 || independentComponents))
3425     {
3426       scalePtr = &volTex->Scale;
3427       biasPtr = &volTex->Bias;
3428     }
3429     vtkInternal::CopyVector<float, 4>(*scalePtr, this->ScaleVec.data(), index * 4);
3430     vtkInternal::CopyVector<float, 4>(*biasPtr, this->BiasVec.data(), index * 4);
3431     vtkInternal::CopyVector<float, 3>(block->CellStep, this->StepVec.data(), index * 3);
3432     vtkInternal::CopyVector<float, 3>(volTex->CellSpacing, this->SpacingVec.data(), index * 3);
3433 
3434     // 8 elements stands for [min, max] per 4-components
3435     vtkInternal::CopyVector<float, 8>(
3436       reinterpret_cast<float*>(volTex->ScalarRange), this->RangeVec.data(), index * 8);
3437 
3438     input.second.ActivateTransferFunction(prog, this->Parent->BlendMode);
3439     index++;
3440   }
3441   prog->SetUniform4fv(
3442     "in_volume_scale", numInputs, reinterpret_cast<const float(*)[4]>(this->ScaleVec.data()));
3443   prog->SetUniform4fv(
3444     "in_volume_bias", numInputs, reinterpret_cast<const float(*)[4]>(this->BiasVec.data()));
3445   prog->SetUniform2fv(
3446     "in_scalarsRange", 4 * numInputs, reinterpret_cast<const float(*)[2]>(this->RangeVec.data()));
3447   prog->SetUniform3fv(
3448     "in_cellStep", numInputs, reinterpret_cast<const float(*)[3]>(this->StepVec.data()));
3449   prog->SetUniform3fv(
3450     "in_cellSpacing", numInputs, reinterpret_cast<const float(*)[3]>(this->SpacingVec.data()));
3451 }
3452 
3453 ////----------------------------------------------------------------------------
SetMapperShaderParameters(vtkShaderProgram * prog,vtkRenderer * ren,int independent,int numComp)3454 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetMapperShaderParameters(
3455   vtkShaderProgram* prog, vtkRenderer* ren, int independent, int numComp)
3456 {
3457   if (!this->SharedDepthTextureObject)
3458   {
3459     this->DepthTextureObject->Activate();
3460   }
3461   prog->SetUniformi("in_depthSampler", this->DepthTextureObject->GetTextureUnit());
3462 
3463   if (this->Parent->GetUseJittering())
3464   {
3465     vtkOpenGLRenderWindow* win = static_cast<vtkOpenGLRenderWindow*>(ren->GetRenderWindow());
3466     prog->SetUniformi("in_noiseSampler", win->GetNoiseTextureUnit());
3467   }
3468 
3469   prog->SetUniformi("in_noOfComponents", numComp);
3470   prog->SetUniformf("in_sampleDistance", this->ActualSampleDistance);
3471 
3472   // Set the scale and bias for color correction
3473   prog->SetUniformf("in_scale", 1.0 / this->Parent->FinalColorWindow);
3474   prog->SetUniformf(
3475     "in_bias", (0.5 - (this->Parent->FinalColorLevel / this->Parent->FinalColorWindow)));
3476   // prog->SetUniformi("in_useTransfer2DGradient", this->Transfer2DUseGradient);
3477   if (!this->Transfer2DUseGradient && this->Transfer2DYAxisScalars)
3478   {
3479     vtkTextureObject* transfer2DYAxisTex =
3480       this->Transfer2DYAxisScalars->GetCurrentBlock()->TextureObject;
3481     transfer2DYAxisTex->Activate();
3482     prog->SetUniformi("in_transfer2DYAxis", transfer2DYAxisTex->GetTextureUnit());
3483     // LargeDataTypes have been already biased and scaled so in those cases 0s
3484     // and 1s are passed respectively.
3485     float tscale[4] = { 1.0, 1.0, 1.0, 1.0 };
3486     float tbias[4] = { 0.0, 0.0, 0.0, 0.0 };
3487     auto volTex = this->Transfer2DYAxisScalars;
3488     auto noOfComponents = volTex->GetLoadedScalars()->GetNumberOfComponents();
3489     if (!volTex->HandleLargeDataTypes &&
3490       (noOfComponents == 1 || noOfComponents == 2 || independent))
3491     {
3492       prog->SetUniform4f("in_transfer2DYAxis_scale", volTex->Scale);
3493       prog->SetUniform4f("in_transfer2DYAxis_bias", volTex->Bias);
3494     }
3495     else
3496     {
3497       prog->SetUniform4f("in_transfer2DYAxis_scale", tscale);
3498       prog->SetUniform4f("in_transfer2DYAxis_bias", tbias);
3499     }
3500   }
3501   else
3502   {
3503     prog->SetUniformi("in_transfer2DYAxis", 0);
3504   }
3505 }
3506 
3507 ////----------------------------------------------------------------------------
SetCameraShaderParameters(vtkShaderProgram * prog,vtkRenderer * ren,vtkOpenGLCamera * cam)3508 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetCameraShaderParameters(
3509   vtkShaderProgram* prog, vtkRenderer* ren, vtkOpenGLCamera* cam)
3510 {
3511   vtkMatrix4x4* glTransformMatrix;
3512   vtkMatrix4x4* modelViewMatrix;
3513   vtkMatrix3x3* normalMatrix;
3514   vtkMatrix4x4* projectionMatrix;
3515   cam->GetKeyMatrices(ren, modelViewMatrix, normalMatrix, projectionMatrix, glTransformMatrix);
3516 
3517   this->InverseProjectionMat->DeepCopy(projectionMatrix);
3518   this->InverseProjectionMat->Invert();
3519   prog->SetUniformMatrix("in_projectionMatrix", projectionMatrix);
3520   prog->SetUniformMatrix("in_inverseProjectionMatrix", this->InverseProjectionMat.GetPointer());
3521 
3522   this->InverseModelViewMat->DeepCopy(modelViewMatrix);
3523   this->InverseModelViewMat->Invert();
3524   prog->SetUniformMatrix("in_modelViewMatrix", modelViewMatrix);
3525   prog->SetUniformMatrix("in_inverseModelViewMatrix", this->InverseModelViewMat.GetPointer());
3526 
3527   float fvalue3[3];
3528   if (cam->GetParallelProjection())
3529   {
3530     double dir[4];
3531     cam->GetDirectionOfProjection(dir);
3532     vtkInternal::ToFloat(dir[0], dir[1], dir[2], fvalue3);
3533     prog->SetUniform3fv("in_projectionDirection", 1, &fvalue3);
3534   }
3535 
3536   vtkInternal::ToFloat(cam->GetPosition(), fvalue3, 3);
3537   prog->SetUniform3fv("in_cameraPos", 1, &fvalue3);
3538 
3539   // TODO Take consideration of reduction factor
3540   float fvalue2[2];
3541   vtkInternal::ToFloat(this->WindowLowerLeft, fvalue2);
3542   prog->SetUniform2fv("in_windowLowerLeftCorner", 1, &fvalue2);
3543 
3544   vtkInternal::ToFloat(1.0 / this->WindowSize[0], 1.0 / this->WindowSize[1], fvalue2);
3545   prog->SetUniform2fv("in_inverseOriginalWindowSize", 1, &fvalue2);
3546 
3547   vtkInternal::ToFloat(1.0 / this->WindowSize[0], 1.0 / this->WindowSize[1], fvalue2);
3548   prog->SetUniform2fv("in_inverseWindowSize", 1, &fvalue2);
3549 }
3550 
3551 //------------------------------------------------------------------------------
SetMaskShaderParameters(vtkShaderProgram * prog,vtkVolumeProperty * prop,int noOfComponents)3552 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetMaskShaderParameters(
3553   vtkShaderProgram* prog, vtkVolumeProperty* prop, int noOfComponents)
3554 {
3555   if (this->CurrentMask)
3556   {
3557     auto maskTex = this->CurrentMask->GetCurrentBlock()->TextureObject;
3558     maskTex->Activate();
3559     prog->SetUniformi("in_mask", maskTex->GetTextureUnit());
3560   }
3561 
3562   if (noOfComponents == 1 && this->Parent->BlendMode != vtkGPUVolumeRayCastMapper::ADDITIVE_BLEND)
3563   {
3564     if (this->Parent->MaskInput != nullptr && this->Parent->MaskType == LabelMapMaskType)
3565     {
3566       this->LabelMapTransfer2D->Activate();
3567       prog->SetUniformi("in_labelMapTransfer", this->LabelMapTransfer2D->GetTextureUnit());
3568       if (prop->HasLabelGradientOpacity())
3569       {
3570         this->LabelMapGradientOpacity->Activate();
3571         prog->SetUniformi(
3572           "in_labelMapGradientOpacity", this->LabelMapGradientOpacity->GetTextureUnit());
3573       }
3574       prog->SetUniformf("in_maskBlendFactor", this->Parent->MaskBlendFactor);
3575       prog->SetUniformf("in_mask_scale", this->CurrentMask->Scale[0]);
3576       prog->SetUniformf("in_mask_bias", this->CurrentMask->Bias[0]);
3577       prog->SetUniformi("in_labelMapNumLabels", this->LabelMapTransfer2D->GetTextureHeight() - 1);
3578     }
3579   }
3580 }
3581 
3582 //------------------------------------------------------------------------------
SetRenderToImageParameters(vtkShaderProgram * prog)3583 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetRenderToImageParameters(
3584   vtkShaderProgram* prog)
3585 {
3586   prog->SetUniformi("in_clampDepthToBackface", this->Parent->GetClampDepthToBackface());
3587 }
3588 
3589 //------------------------------------------------------------------------------
SetAdvancedShaderParameters(vtkRenderer * ren,vtkShaderProgram * prog,vtkVolume * vol,vtkVolumeTexture::VolumeBlock * block,int numComp)3590 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::SetAdvancedShaderParameters(vtkRenderer* ren,
3591   vtkShaderProgram* prog, vtkVolume* vol, vtkVolumeTexture::VolumeBlock* block, int numComp)
3592 {
3593   // Cropping and clipping
3594   auto bounds = block->LoadedBoundsAA;
3595   this->SetCroppingRegions(prog, bounds);
3596   this->SetClippingPlanes(ren, prog, vol);
3597 
3598   // Picking
3599   if (this->CurrentSelectionPass < vtkHardwareSelector::POINT_ID_LOW24)
3600   {
3601     this->SetPickingId(ren);
3602   }
3603 
3604   auto blockExt = block->Extents;
3605   float fvalue3[3];
3606   vtkInternal::ToFloat(blockExt[0], blockExt[2], blockExt[4], fvalue3);
3607   prog->SetUniform3fv("in_textureExtentsMin", 1, &fvalue3);
3608 
3609   vtkInternal::ToFloat(blockExt[1], blockExt[3], blockExt[5], fvalue3);
3610   prog->SetUniform3fv("in_textureExtentsMax", 1, &fvalue3);
3611 
3612   // Component weights (independent components)
3613   auto volProperty = vol->GetProperty();
3614   float fvalue4[4];
3615   if (numComp > 1 && volProperty->GetIndependentComponents())
3616   {
3617     for (int i = 0; i < numComp; ++i)
3618     {
3619       fvalue4[i] = static_cast<float>(volProperty->GetComponentWeight(i));
3620     }
3621     prog->SetUniform4fv("in_componentWeight", 1, &fvalue4);
3622   }
3623 
3624   // Set the scalar range to be considered for average ip blend
3625   double avgRange[2];
3626   float fvalue2[2];
3627   this->Parent->GetAverageIPScalarRange(avgRange);
3628   if (avgRange[1] < avgRange[0])
3629   {
3630     double tmp = avgRange[1];
3631     avgRange[1] = avgRange[0];
3632     avgRange[0] = tmp;
3633   }
3634   vtkInternal::ToFloat(avgRange[0], avgRange[1], fvalue2);
3635   prog->SetUniform2fv("in_averageIPRange", 1, &fvalue2);
3636 
3637   // Set contour values for isosurface blend mode
3638   //--------------------------------------------------------------------------
3639   if (this->Parent->BlendMode == vtkVolumeMapper::ISOSURFACE_BLEND)
3640   {
3641     vtkIdType nbContours = volProperty->GetIsoSurfaceValues()->GetNumberOfContours();
3642 
3643     std::vector<float> values(nbContours);
3644     for (int i = 0; i < nbContours; i++)
3645     {
3646       values[i] = static_cast<float>(volProperty->GetIsoSurfaceValues()->GetValue(i));
3647     }
3648 
3649     // The shader expect (for efficiency purposes) the isovalues to be sorted.
3650     std::sort(values.begin(), values.end());
3651 
3652     prog->SetUniform1fv("in_isosurfacesValues", nbContours, values.data());
3653   }
3654 
3655   // Set function attributes for slice blend mode
3656   //--------------------------------------------------------------------------
3657   if (this->Parent->BlendMode == vtkVolumeMapper::SLICE_BLEND)
3658   {
3659     vtkPlane* plane = vtkPlane::SafeDownCast(volProperty->GetSliceFunction());
3660 
3661     if (plane)
3662     {
3663       double planeOrigin[3];
3664       double planeNormal[3];
3665 
3666       plane->GetOrigin(planeOrigin);
3667       plane->GetNormal(planeNormal);
3668 
3669       prog->SetUniform3f("in_slicePlaneOrigin", planeOrigin);
3670       prog->SetUniform3f("in_slicePlaneNormal", planeNormal);
3671     }
3672   }
3673 }
3674 
FinishRendering(const int numComp)3675 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::FinishRendering(const int numComp)
3676 {
3677   for (auto& item : this->Parent->AssembledInputs)
3678   {
3679     auto& input = item.second;
3680     input.Texture->GetCurrentBlock()->TextureObject->Deactivate();
3681     input.DeactivateTransferFunction(this->Parent->BlendMode);
3682   }
3683 
3684   if (this->DepthTextureObject && !this->SharedDepthTextureObject)
3685   {
3686     this->DepthTextureObject->Deactivate();
3687   }
3688 
3689   if (this->CurrentMask)
3690   {
3691     this->CurrentMask->GetCurrentBlock()->TextureObject->Deactivate();
3692   }
3693 
3694   if (numComp == 1 && this->Parent->BlendMode != vtkGPUVolumeRayCastMapper::ADDITIVE_BLEND)
3695   {
3696     if (this->Parent->MaskInput != nullptr && this->Parent->MaskType == LabelMapMaskType)
3697     {
3698       this->LabelMapTransfer2D->Deactivate();
3699       this->LabelMapGradientOpacity->Deactivate();
3700     }
3701   }
3702 
3703   vtkOpenGLStaticCheckErrorMacro("Failed after FinishRendering!");
3704 }
3705 
3706 //------------------------------------------------------------------------------
DoGPURender(vtkRenderer * ren,vtkOpenGLCamera * cam,vtkShaderProgram * prog,vtkOpenGLShaderProperty * shaderProperty)3707 void vtkOpenGLGPUVolumeRayCastMapper::DoGPURender(vtkRenderer* ren, vtkOpenGLCamera* cam,
3708   vtkShaderProgram* prog, vtkOpenGLShaderProperty* shaderProperty)
3709 {
3710   if (!prog)
3711   {
3712     return;
3713   }
3714 
3715   // Upload the value of user-defined uniforms in the program
3716   auto vu = static_cast<vtkOpenGLUniforms*>(shaderProperty->GetVertexCustomUniforms());
3717   vu->SetUniforms(prog);
3718   auto fu = static_cast<vtkOpenGLUniforms*>(shaderProperty->GetFragmentCustomUniforms());
3719   fu->SetUniforms(prog);
3720   auto gu = static_cast<vtkOpenGLUniforms*>(shaderProperty->GetGeometryCustomUniforms());
3721   gu->SetUniforms(prog);
3722 
3723   this->SetShaderParametersRenderPass();
3724   if (!this->Impl->MultiVolume)
3725   {
3726     this->Impl->RenderSingleInput(ren, cam, prog);
3727   }
3728   else
3729   {
3730     this->Impl->RenderMultipleInputs(ren, cam, prog);
3731   }
3732 }
3733 
3734 //------------------------------------------------------------------------------
RenderMultipleInputs(vtkRenderer * ren,vtkOpenGLCamera * cam,vtkShaderProgram * prog)3735 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::RenderMultipleInputs(
3736   vtkRenderer* ren, vtkOpenGLCamera* cam, vtkShaderProgram* prog)
3737 {
3738   auto& input = this->Parent->AssembledInputs[0];
3739   auto vol = input.Volume;
3740   auto volumeTex = input.Texture.GetPointer();
3741   const int independent = vol->GetProperty()->GetIndependentComponents();
3742   const int numComp = volumeTex->GetLoadedScalars()->GetNumberOfComponents();
3743   int const numSamplers = (independent ? numComp : 1);
3744   auto geometry = this->MultiVolume->GetDataGeometry();
3745 
3746   vtkMatrix4x4 *wcvc, *vcdc, *wcdc;
3747   vtkMatrix3x3* norm;
3748   cam->GetKeyMatrices(ren, wcvc, norm, vcdc, wcdc);
3749 
3750   this->SetMapperShaderParameters(prog, ren, independent, numComp);
3751   this->SetVolumeShaderParameters(prog, independent, numComp, wcvc);
3752   this->SetLightingShaderParameters(ren, prog, this->MultiVolume, numSamplers);
3753   this->SetCameraShaderParameters(prog, ren, cam);
3754 
3755   this->SetClippingPlanes(ren, prog, this->MultiVolume);
3756 
3757   this->RenderVolumeGeometry(ren, prog, this->MultiVolume, geometry);
3758   this->FinishRendering(numComp);
3759 }
3760 
3761 //------------------------------------------------------------------------------
RenderSingleInput(vtkRenderer * ren,vtkOpenGLCamera * cam,vtkShaderProgram * prog)3762 void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::RenderSingleInput(
3763   vtkRenderer* ren, vtkOpenGLCamera* cam, vtkShaderProgram* prog)
3764 {
3765   auto& input = this->Parent->AssembledInputs[0];
3766   auto vol = input.Volume;
3767   auto volumeTex = input.Texture.GetPointer();
3768 
3769   // Sort blocks in case the viewpoint changed, it immediately returns if there
3770   // is a single block.
3771   volumeTex->SortBlocksBackToFront(ren, vol->GetMatrix());
3772   vtkVolumeTexture::VolumeBlock* block = volumeTex->GetCurrentBlock();
3773 
3774   if (this->CurrentMask)
3775   {
3776     this->CurrentMask->SortBlocksBackToFront(ren, vol->GetMatrix());
3777   }
3778 
3779   const int independent = vol->GetProperty()->GetIndependentComponents();
3780   const int numComp = volumeTex->GetLoadedScalars()->GetNumberOfComponents();
3781   while (block != nullptr)
3782   {
3783     const int numSamplers = (independent ? numComp : 1);
3784     this->SetMapperShaderParameters(prog, ren, independent, numComp);
3785 
3786     vtkMatrix4x4 *wcvc, *vcdc, *wcdc;
3787     vtkMatrix3x3* norm;
3788     cam->GetKeyMatrices(ren, wcvc, norm, vcdc, wcdc);
3789     this->SetVolumeShaderParameters(prog, independent, numComp, wcvc);
3790 
3791     this->SetMaskShaderParameters(prog, vol->GetProperty(), numComp);
3792     this->SetLightingShaderParameters(ren, prog, vol, numSamplers);
3793     this->SetCameraShaderParameters(prog, ren, cam);
3794     this->SetAdvancedShaderParameters(ren, prog, vol, block, numComp);
3795 
3796     this->RenderVolumeGeometry(ren, prog, vol, block->VolumeGeometry);
3797 
3798     this->FinishRendering(numComp);
3799     block = volumeTex->GetNextBlock();
3800     if (this->CurrentMask)
3801     {
3802       this->CurrentMask->GetNextBlock();
3803     }
3804   }
3805 }
3806 
3807 //------------------------------------------------------------------------------
SetPartitions(unsigned short x,unsigned short y,unsigned short z)3808 void vtkOpenGLGPUVolumeRayCastMapper::SetPartitions(
3809   unsigned short x, unsigned short y, unsigned short z)
3810 {
3811   this->Impl->Partitions[0] = x;
3812   this->Impl->Partitions[1] = y;
3813   this->Impl->Partitions[2] = z;
3814 }
3815 
3816 //------------------------------------------------------------------------------
GetRenderPassStageMTime(vtkVolume * vol)3817 vtkMTimeType vtkOpenGLGPUVolumeRayCastMapper::GetRenderPassStageMTime(vtkVolume* vol)
3818 {
3819   vtkInformation* info = vol->GetPropertyKeys();
3820   vtkMTimeType renderPassMTime = 0;
3821 
3822   int curRenderPasses = 0;
3823   this->Impl->RenderPassAttached = false;
3824   if (info && info->Has(vtkOpenGLRenderPass::RenderPasses()))
3825   {
3826     curRenderPasses = info->Length(vtkOpenGLRenderPass::RenderPasses());
3827     this->Impl->RenderPassAttached = true;
3828   }
3829 
3830   int lastRenderPasses = 0;
3831   if (this->LastRenderPassInfo->Has(vtkOpenGLRenderPass::RenderPasses()))
3832   {
3833     lastRenderPasses = this->LastRenderPassInfo->Length(vtkOpenGLRenderPass::RenderPasses());
3834   }
3835 
3836   // Determine the last time a render pass changed stages:
3837   if (curRenderPasses != lastRenderPasses)
3838   {
3839     // Number of passes changed, definitely need to update.
3840     // Fake the time to force an update:
3841     renderPassMTime = VTK_MTIME_MAX;
3842   }
3843   else
3844   {
3845     // Compare the current to the previous render passes:
3846     for (int i = 0; i < curRenderPasses; ++i)
3847     {
3848       vtkObjectBase* curRP = info->Get(vtkOpenGLRenderPass::RenderPasses(), i);
3849       vtkObjectBase* lastRP = this->LastRenderPassInfo->Get(vtkOpenGLRenderPass::RenderPasses(), i);
3850 
3851       if (curRP != lastRP)
3852       {
3853         // Render passes have changed. Force update:
3854         renderPassMTime = VTK_MTIME_MAX;
3855         break;
3856       }
3857       else
3858       {
3859         // Render passes have not changed -- check MTime.
3860         vtkOpenGLRenderPass* rp = static_cast<vtkOpenGLRenderPass*>(curRP);
3861         renderPassMTime = std::max(renderPassMTime, rp->GetShaderStageMTime());
3862       }
3863     }
3864   }
3865 
3866   // Cache the current set of render passes for next time:
3867   if (info)
3868   {
3869     this->LastRenderPassInfo->CopyEntry(info, vtkOpenGLRenderPass::RenderPasses());
3870   }
3871   else
3872   {
3873     this->LastRenderPassInfo->Clear();
3874   }
3875 
3876   return renderPassMTime;
3877 }
3878 
3879 //------------------------------------------------------------------------------
ReplaceShaderRenderPass(std::map<vtkShader::Type,vtkShader * > & shaders,vtkVolume * vol,bool prePass)3880 void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderRenderPass(
3881   std::map<vtkShader::Type, vtkShader*>& shaders, vtkVolume* vol, bool prePass)
3882 {
3883   std::string vertShader = shaders[vtkShader::Vertex]->GetSource();
3884   std::string geomShader = shaders[vtkShader::Geometry]->GetSource();
3885   std::string fragShader = shaders[vtkShader::Fragment]->GetSource();
3886   vtkInformation* info = vol->GetPropertyKeys();
3887   if (info && info->Has(vtkOpenGLRenderPass::RenderPasses()))
3888   {
3889     int numRenderPasses = info->Length(vtkOpenGLRenderPass::RenderPasses());
3890     for (int i = 0; i < numRenderPasses; ++i)
3891     {
3892       vtkObjectBase* rpBase = info->Get(vtkOpenGLRenderPass::RenderPasses(), i);
3893       vtkOpenGLRenderPass* rp = static_cast<vtkOpenGLRenderPass*>(rpBase);
3894       if (prePass)
3895       {
3896         if (!rp->PreReplaceShaderValues(vertShader, geomShader, fragShader, this, vol))
3897         {
3898           vtkErrorMacro(
3899             "vtkOpenGLRenderPass::PreReplaceShaderValues failed for " << rp->GetClassName());
3900         }
3901       }
3902       else
3903       {
3904         if (!rp->PostReplaceShaderValues(vertShader, geomShader, fragShader, this, vol))
3905         {
3906           vtkErrorMacro(
3907             "vtkOpenGLRenderPass::PostReplaceShaderValues failed for " << rp->GetClassName());
3908         }
3909       }
3910     }
3911   }
3912   shaders[vtkShader::Vertex]->SetSource(vertShader);
3913   shaders[vtkShader::Geometry]->SetSource(geomShader);
3914   shaders[vtkShader::Fragment]->SetSource(fragShader);
3915 }
3916 
3917 //------------------------------------------------------------------------------
SetShaderParametersRenderPass()3918 void vtkOpenGLGPUVolumeRayCastMapper::SetShaderParametersRenderPass()
3919 {
3920   auto vol = this->Impl->GetActiveVolume();
3921   vtkInformation* info = vol->GetPropertyKeys();
3922   if (info && info->Has(vtkOpenGLRenderPass::RenderPasses()))
3923   {
3924     int numRenderPasses = info->Length(vtkOpenGLRenderPass::RenderPasses());
3925     for (int i = 0; i < numRenderPasses; ++i)
3926     {
3927       vtkObjectBase* rpBase = info->Get(vtkOpenGLRenderPass::RenderPasses(), i);
3928       vtkOpenGLRenderPass* rp = static_cast<vtkOpenGLRenderPass*>(rpBase);
3929       if (!rp->SetShaderParameters(this->Impl->ShaderProgram, this, vol))
3930       {
3931         vtkErrorMacro(
3932           "RenderPass::SetShaderParameters failed for renderpass: " << rp->GetClassName());
3933       }
3934     }
3935   }
3936 }
3937