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