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