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