1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkGPUVolumeRayCastMapper.h 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 * @class vtkGPUVolumeRayCastMapper 17 * @brief Ray casting performed on the GPU. 18 * 19 * vtkGPUVolumeRayCastMapper is a volume mapper that performs ray casting on 20 * the GPU using fragment programs. 21 * 22 * This mapper supports connections in multiple ports of input 0 (port 0 being 23 * the only required connection). It is up to the concrete implementation 24 * whether additional inputs will be used during rendering. This class maintains 25 * a list of the currently active input ports (Ports) as well as a list of the 26 * ports that have been disconnected (RemovedPorts). RemovedPorts is used the 27 * the concrete implementation to clean up internal structures. 28 * 29 */ 30 #ifndef vtkGPUVolumeRayCastMapper_h 31 #define vtkGPUVolumeRayCastMapper_h 32 #include <unordered_map> // For std::unordered_map 33 #include <vector> // For std::vector 34 35 #include <vtkRenderingVolumeModule.h> // For export macro 36 #include "vtkVolumeMapper.h" 37 38 39 class vtkContourValues; 40 class vtkRenderWindow; 41 class vtkVolumeProperty; 42 43 class VTKRENDERINGVOLUME_EXPORT vtkGPUVolumeRayCastMapper : public vtkVolumeMapper 44 { 45 public: 46 static vtkGPUVolumeRayCastMapper *New(); 47 vtkTypeMacro(vtkGPUVolumeRayCastMapper,vtkVolumeMapper); 48 void PrintSelf( ostream& os, vtkIndent indent ) override; 49 50 //@{ 51 /** 52 * If AutoAdjustSampleDistances is on, the ImageSampleDistance 53 * will be varied to achieve the allocated render time of this 54 * prop (controlled by the desired update rate and any culling in 55 * use). 56 */ 57 vtkSetClampMacro( AutoAdjustSampleDistances, vtkTypeBool, 0, 1 ); 58 vtkGetMacro( AutoAdjustSampleDistances, vtkTypeBool ); 59 vtkBooleanMacro( AutoAdjustSampleDistances, vtkTypeBool ); 60 //@} 61 62 //@{ 63 /** 64 * Compute the sample distance from the data spacing. When the number of 65 * voxels is 8, the sample distance will be roughly 1/200 the average voxel 66 * size. The distance will grow proportionally to numVoxels^(1/3). Off by default. 67 */ 68 vtkSetClampMacro( LockSampleDistanceToInputSpacing, vtkTypeBool, 0, 1 ); 69 vtkGetMacro( LockSampleDistanceToInputSpacing, vtkTypeBool ); 70 vtkBooleanMacro( LockSampleDistanceToInputSpacing, vtkTypeBool ); 71 //@} 72 73 //@{ 74 /** 75 * If UseJittering is on, each ray traversal direction will be 76 * perturbed slightly using a noise-texture to get rid of wood-grain 77 * effect. 78 */ 79 vtkSetClampMacro( UseJittering, vtkTypeBool, 0, 1 ); 80 vtkGetMacro( UseJittering, vtkTypeBool ); 81 vtkBooleanMacro( UseJittering, vtkTypeBool ); 82 //@} 83 84 //@{ 85 /** 86 * If UseDepthPass is on, the mapper will use two passes. In the first 87 * pass, an isocontour depth buffer will be utilized as starting point 88 * for ray-casting hence eliminating traversal on voxels that are 89 * not going to participate in final rendering. UseDepthPass requires 90 * reasonable contour values to be set which can be set by calling 91 * GetDepthPassContourValues() method and using vtkControurValues API. 92 */ 93 vtkSetClampMacro( UseDepthPass, vtkTypeBool, 0, 1 ); 94 vtkGetMacro( UseDepthPass, vtkTypeBool ); 95 vtkBooleanMacro( UseDepthPass, vtkTypeBool ); 96 //@} 97 98 /** 99 * Return handle to contour values container so 100 * that values can be set by the application. Contour values 101 * will be used only when UseDepthPass is on. 102 */ 103 vtkContourValues* GetDepthPassContourValues(); 104 105 //@{ 106 /** 107 * Set/Get the distance between samples used for rendering 108 * when AutoAdjustSampleDistances is off, or when this mapper 109 * has more than 1 second allocated to it for rendering. 110 * Initial value is 1.0. 111 */ 112 vtkSetMacro( SampleDistance, float ); 113 vtkGetMacro( SampleDistance, float ); 114 //@} 115 116 //@{ 117 /** 118 * Sampling distance in the XY image dimensions. Default value of 1 meaning 119 * 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If 120 * set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. This value 121 * will be adjusted to meet a desired frame rate when AutoAdjustSampleDistances 122 * is on. 123 */ 124 vtkSetClampMacro( ImageSampleDistance, float, 0.1f, 100.0f ); 125 vtkGetMacro( ImageSampleDistance, float ); 126 //@} 127 128 //@{ 129 /** 130 * This is the minimum image sample distance allow when the image 131 * sample distance is being automatically adjusted. 132 */ 133 vtkSetClampMacro( MinimumImageSampleDistance, float, 0.1f, 100.0f ); 134 vtkGetMacro( MinimumImageSampleDistance, float ); 135 //@} 136 137 //@{ 138 /** 139 * This is the maximum image sample distance allow when the image 140 * sample distance is being automatically adjusted. 141 */ 142 vtkSetClampMacro( MaximumImageSampleDistance, float, 0.1f, 100.0f ); 143 vtkGetMacro( MaximumImageSampleDistance, float ); 144 //@} 145 146 147 //@{ 148 /** 149 * Set/Get the window / level applied to the final color. 150 * This allows brightness / contrast adjustments on the 151 * final image. 152 * window is the width of the window. 153 * level is the center of the window. 154 * Initial window value is 1.0 155 * Initial level value is 0.5 156 * window cannot be null but can be negative, this way 157 * values will be reversed. 158 * |window| can be larger than 1.0 159 * level can be any real value. 160 */ 161 vtkSetMacro( FinalColorWindow, float ); 162 vtkGetMacro( FinalColorWindow, float ); 163 vtkSetMacro( FinalColorLevel, float ); 164 vtkGetMacro( FinalColorLevel, float ); 165 //@} 166 167 //@{ 168 /** 169 * Maximum size of the 3D texture in GPU memory. 170 * Will default to the size computed from the graphics 171 * card. Can be adjusted by the user. 172 */ 173 vtkSetMacro( MaxMemoryInBytes, vtkIdType ); 174 vtkGetMacro( MaxMemoryInBytes, vtkIdType ); 175 //@} 176 177 //@{ 178 /** 179 * Maximum fraction of the MaxMemoryInBytes that should 180 * be used to hold the texture. Valid values are 0.1 to 181 * 1.0. 182 */ 183 vtkSetClampMacro( MaxMemoryFraction, float, 0.1f, 1.0f ); 184 vtkGetMacro( MaxMemoryFraction, float ); 185 //@} 186 187 //@{ 188 /** 189 * Tells if the mapper will report intermediate progress. 190 * Initial value is true. As the progress works with a GL blocking 191 * call (glFinish()), this can be useful for huge dataset but can 192 * slow down rendering of small dataset. It should be set to true 193 * for big dataset or complex shading and streaming but to false for 194 * small datasets. 195 */ 196 vtkSetMacro(ReportProgress,bool); 197 vtkGetMacro(ReportProgress,bool); 198 //@} 199 200 /** 201 * Based on hardware and properties, we may or may not be able to 202 * render using 3D texture mapping. This indicates if 3D texture 203 * mapping is supported by the hardware, and if the other extensions 204 * necessary to support the specific properties are available. 205 */ IsRenderSupported(vtkRenderWindow * vtkNotUsed (window),vtkVolumeProperty * vtkNotUsed (property))206 virtual int IsRenderSupported(vtkRenderWindow *vtkNotUsed(window), 207 vtkVolumeProperty *vtkNotUsed(property)) 208 { 209 return 0; 210 } 211 212 void CreateCanonicalView( vtkRenderer *ren, 213 vtkVolume *volume, 214 vtkImageData *image, 215 int blend_mode, 216 double viewDirection[3], 217 double viewUp[3] ); 218 219 //@{ 220 /** 221 * Optionally, set a mask input. This mask may be a binary mask or a label 222 * map. This must be specified via SetMaskType. 223 224 * If the mask is a binary mask, the volume rendering is confined to regions 225 * within the binary mask. The binary mask is assumed to have a datatype of 226 * UCHAR and values of 255 (inside) and 0 (outside). 227 228 * The mask may also be a label map. The label map is allowed to contain only 229 * 3 labels (values of 0, 1 and 2) and must have a datatype of UCHAR. In voxels 230 * with label value of 0, the color transfer function supplied by component 231 * 0 is used. 232 * In voxels with label value of 1, the color transfer function supplied by 233 * component 1 is used and blended with the transfer function supplied by 234 * component 0, with the blending weight being determined by 235 * MaskBlendFactor. 236 * In voxels with a label value of 2, the color transfer function supplied 237 * by component 2 is used and blended with the transfer function supplied by 238 * component 0, with the blending weight being determined by 239 * MaskBlendFactor. 240 */ 241 void SetMaskInput(vtkImageData *mask); 242 vtkGetObjectMacro(MaskInput, vtkImageData); 243 //@} 244 245 enum { BinaryMaskType = 0, LabelMapMaskType }; 246 247 //@{ 248 /** 249 * Set the mask type, if mask is to be used. See documentation for 250 * SetMaskInput(). The default is a LabelMapMaskType. 251 */ 252 vtkSetMacro( MaskType, int ); 253 vtkGetMacro( MaskType, int ); 254 void SetMaskTypeToBinary(); 255 void SetMaskTypeToLabelMap(); 256 //@} 257 258 //@{ 259 /** 260 * Tells how much mask color transfer function is used compared to the 261 * standard color transfer function when the mask is true. This is relevant 262 * only for the label map mask. 263 * 0.0 means only standard color transfer function. 264 * 1.0 means only mask color transfer function. 265 * The default value is 1.0. 266 */ 267 vtkSetClampMacro(MaskBlendFactor,float,0.0f,1.0f); 268 vtkGetMacro(MaskBlendFactor,float); 269 //@} 270 271 //@{ 272 /** 273 * Enable or disable setting output of volume rendering to be 274 * color and depth textures. By default this is set to 0 (off). 275 * It should be noted that it is possible that underlying API specific 276 * mapper may not supoport RenderToImage mode. 277 * \warning 278 * \li This method ignores any other volumes / props in the scene. 279 * \li This method does not respect the general attributes of the 280 * scene i.e. background color, etc. It always produces a color 281 * image that has a transparent white background outside the 282 * bounds of the volume. 283 284 * \sa GetDepthImage(), GetColorImage() 285 */ 286 vtkSetMacro(RenderToImage, vtkTypeBool); 287 vtkGetMacro(RenderToImage, vtkTypeBool); 288 vtkBooleanMacro(RenderToImage, vtkTypeBool); 289 //@} 290 291 //@{ 292 /** 293 * Set/Get the scalar type of the depth texture in RenderToImage mode. 294 * By default, the type if VTK_FLOAT. 295 * \sa SetRenderToImage() 296 */ 297 vtkSetMacro(DepthImageScalarType, int); 298 vtkGetMacro(DepthImageScalarType, int); 299 void SetDepthImageScalarTypeToUnsignedChar(); 300 void SetDepthImageScalarTypeToUnsignedShort(); 301 void SetDepthImageScalarTypeToFloat(); 302 //@} 303 304 //@{ 305 /** 306 * Enable or disable clamping the depth value of the fully 307 * transparent voxel to the depth of the back-face of the 308 * volume. This parameter is used when RenderToImage mode is 309 * enabled. When ClampDepthToBackFace is false, the fully transparent 310 * voxels will have a value of 1.0 in the depth image. When 311 * this is true, the fully transparent voxels will have the 312 * depth value of the face at which the ray exits the volume. 313 * By default, this is set to 0 (off). 314 * \sa SetRenderToImage(), GetDepthImage() 315 */ 316 vtkSetMacro(ClampDepthToBackface, vtkTypeBool); 317 vtkGetMacro(ClampDepthToBackface, vtkTypeBool); 318 vtkBooleanMacro(ClampDepthToBackface, vtkTypeBool); 319 //@} 320 321 /** 322 * Low level API to export the depth texture as vtkImageData in 323 * RenderToImage mode. 324 * Should be implemented by the graphics API specific mapper (GL or other). 325 * \sa SetRenderToImage() 326 */ GetDepthImage(vtkImageData *)327 virtual void GetDepthImage(vtkImageData*) {}; 328 329 /** 330 * Low level API to export the color texture as vtkImageData in 331 * RenderToImage mode. 332 * Should be implemented by the graphics API specific mapper (GL or other). 333 * \sa SetRenderToImage() 334 */ GetColorImage(vtkImageData *)335 virtual void GetColorImage(vtkImageData*) {}; 336 337 /** 338 * Initialize rendering for this volume. 339 * \warning INTERNAL METHOD - NOT INTENDED FOR GENERAL USE 340 */ 341 void Render( vtkRenderer *, vtkVolume * ) override; 342 343 /** 344 * Handled in the subclass - the actual render method 345 * \pre input is up-to-date. 346 */ GPURender(vtkRenderer *,vtkVolume *)347 virtual void GPURender( vtkRenderer *, vtkVolume *) {} 348 349 /** 350 * Release any graphics resources that are being consumed by this mapper. 351 * The parameter window could be used to determine which graphic 352 * resources to release. 353 * \warning INTERNAL METHOD - NOT INTENDED FOR GENERAL USE 354 */ ReleaseGraphicsResources(vtkWindow *)355 void ReleaseGraphicsResources(vtkWindow *) override {} 356 357 /** 358 * Return how much the dataset has to be reduced in each dimension to 359 * fit on the GPU. If the value is 1.0, there is no need to reduce the 360 * dataset. 361 * \pre the calling thread has a current OpenGL context. 362 * \pre mapper_supported: IsRenderSupported(renderer->GetRenderWindow(),0) 363 * The computation is based on hardware limits (3D texture indexable size) 364 * and MaxMemoryInBytes. 365 * \post valid_i_ratio: ratio[0]>0 && ratio[0]<=1.0 366 * \post valid_j_ratio: ratio[1]>0 && ratio[1]<=1.0 367 * \post valid_k_ratio: ratio[2]>0 && ratio[2]<=1.0 368 */ 369 virtual void GetReductionRatio(double ratio[3])=0; 370 371 enum TFRangeType 372 { 373 SCALAR = 0, // default 374 NATIVE 375 }; 376 377 //@{ 378 /** 379 * Set whether to use the scalar range or the native transfer function range 380 * when looking up transfer functions for color and opacity values. When the 381 * range is set to TransferFunctionRange::SCALAR, the function is distributed 382 * over the entire scalar range. If it is set to 383 * TransferFunctionRange::NATIVE, the scalar values outside the native 384 * transfer function range will be truncated to native range. By 385 * default, the volume scalar range is used. 386 * 387 * \note The native range of the transfer function is the range returned by 388 * vtkColorTransferFunction::GetRange() or vtkPiecewiseFunction::GetRange(). 389 * 390 * \note There is no special API provided for 2D transfer functions 391 * considering that they are set as a pre-generated vtkImageData on this 392 * class i.e. the range is already encoded. 393 */ 394 vtkSetMacro(ColorRangeType, int); 395 vtkGetMacro(ColorRangeType, int); 396 vtkSetMacro(ScalarOpacityRangeType, int); 397 vtkGetMacro(ScalarOpacityRangeType, int); 398 vtkSetMacro(GradientOpacityRangeType, int); 399 vtkGetMacro(GradientOpacityRangeType, int); 400 //@} 401 GetInput()402 vtkImageData* GetInput() override 403 { 404 return this->GetInput(0); 405 }; 406 407 //@{ 408 /** 409 * Add/Remove input connections. Active and removed ports are cached in 410 * Ports and RemovedPorts respectively. 411 */ 412 void RemoveInputConnection(int port, vtkAlgorithmOutput* input) override; 413 void RemoveInputConnection(int port, int idx) override; 414 void SetInputConnection(int port, vtkAlgorithmOutput* input) override; SetInputConnection(vtkAlgorithmOutput * input)415 void SetInputConnection(vtkAlgorithmOutput* input) override 416 { 417 this->SetInputConnection(0, input); 418 } 419 //@} 420 421 /** 422 * Number of currently active ports. 423 */ 424 int GetInputCount(); 425 426 vtkImageData* GetTransformedInput(const int port = 0); 427 428 double* GetBoundsFromPort(const int port) VTK_SIZEHINT(6); 429 430 protected: 431 vtkGPUVolumeRayCastMapper(); 432 ~vtkGPUVolumeRayCastMapper() override; 433 434 /** 435 * Handle inputs. This mapper provides an interface to support multiple 436 * inputs but it is up to the OpenGL implementation use them during rendering. 437 * Currently, only VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper makes use 438 * of these inputs. 439 * 440 * \sa vtkOpenGLGPUVolumeRayCastMapper vtkMultiVolume 441 */ 442 int FillInputPortInformation(int port, vtkInformation* info) override; 443 444 /** 445 * A transformation is applied (translation) to the input. The resulting 446 * data is stored in TransformedInputs. Takes as an argumet the port of an 447 * input connection. 448 * 449 * ///TODO Elaborate on why this is an issue, texture coords (?) 450 * @TODO: This is the workaround to deal with GPUVolumeRayCastMapper 451 * not able to handle extents starting from non zero values. 452 * There is not a easy fix in the GPU volume ray cast mapper hence 453 * this fix has been introduced. 454 */ 455 void TransformInput(const int port); 456 457 //@{ 458 /** 459 * This method is used by the Render() method to validate everything before 460 * attempting to render. This method returns 0 if something is not right - 461 * such as missing input, a null renderer or a null volume, no scalars, etc. 462 * In some cases it will produce a vtkErrorMacro message, and in others 463 * (for example, in the case of cropping planes that define a region with 464 * a volume or 0 or less) it will fail silently. If everything is OK, it will 465 * return with a value of 1. 466 */ 467 int ValidateRender( vtkRenderer *, vtkVolume * ); 468 int ValidateInputs(); 469 int ValidateInput(vtkVolumeProperty* property, const int port); 470 //@} 471 472 //@{ 473 /** 474 * Shallow-copy the inputs into a transform-adjusted clone. 475 * \sa vtkGPUVolumeRayCastMapper::TransformInput 476 */ 477 void CloneInputs(); 478 void CloneInput(vtkImageData* input, const int port); 479 //@} 480 481 // Special version of render called during the creation 482 // of a canonical view. 483 void CanonicalViewRender( vtkRenderer *, vtkVolume * ); 484 485 // Methods called by the AMR Volume Mapper. 486 virtual void PreRender(vtkRenderer *ren, 487 vtkVolume *vol, 488 double datasetBounds[6], 489 double scalarRange[2], 490 int numberOfScalarComponents, 491 unsigned int numberOfLevels)=0; 492 493 // \pre input is up-to-date 494 virtual void RenderBlock(vtkRenderer *ren, 495 vtkVolume *vol, 496 unsigned int level)=0; 497 498 virtual void PostRender(vtkRenderer *ren, 499 int numberOfScalarComponents)=0; 500 vtkImageData* GetInput(const int port) override; 501 502 /** 503 * Called by the AMR Volume Mapper. 504 * Set the flag that tells if the scalars are on point data (0) or 505 * cell data (1). 506 */ 507 void SetCellFlag(int cellFlag); 508 void RemovePortInternal(const int port); 509 510 vtkTypeBool LockSampleDistanceToInputSpacing; 511 vtkTypeBool AutoAdjustSampleDistances; 512 float ImageSampleDistance; 513 float MinimumImageSampleDistance; 514 float MaximumImageSampleDistance; 515 516 // Render to texture mode flag 517 vtkTypeBool RenderToImage; 518 519 // Depth image scalar type 520 int DepthImageScalarType; 521 522 // Clamp depth values to the depth of the face at which the ray 523 // exits the volume 524 vtkTypeBool ClampDepthToBackface; 525 526 // Enable / disable stochastic jittering 527 vtkTypeBool UseJittering; 528 529 // Enable / disable two pass rendering 530 vtkTypeBool UseDepthPass; 531 vtkContourValues* DepthPassContourValues; 532 533 // The distance between sample points along the ray 534 float SampleDistance; 535 536 int SmallVolumeRender; 537 double BigTimeToDraw; 538 double SmallTimeToDraw; 539 540 float FinalColorWindow; 541 float FinalColorLevel; 542 543 // 1 if we are generating the canonical image, 0 otherwise 544 int GeneratingCanonicalView; 545 vtkImageData *CanonicalViewImageData; 546 547 //@{ 548 /** 549 * Set the mapper in AMR Mode or not. Initial value is false. 550 * Called only by the vtkKWAMRVolumeMapper 551 */ 552 vtkSetClampMacro(AMRMode,vtkTypeBool,0,1); 553 vtkGetMacro(AMRMode,vtkTypeBool); 554 vtkBooleanMacro(AMRMode,vtkTypeBool); 555 //@} 556 557 vtkImageData * MaskInput; 558 float MaskBlendFactor; 559 int MaskType; 560 561 vtkTypeBool AMRMode; 562 563 // Transfer function range type 564 int ColorRangeType; 565 int ScalarOpacityRangeType; 566 int GradientOpacityRangeType; 567 568 // Point data or cell data (or field data, not handled) ? 569 int CellFlag; 570 571 /** 572 * Compute the cropping planes clipped by the bounds of the volume. 573 * The result is put into this->ClippedCroppingRegionPlanes. 574 * NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage 575 * in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes 576 * members instead of CroppingRegionPlanes. 577 * \pre volume_exists: this->GetInput()!=0 578 * \pre valid_cropping: this->Cropping && 579 * this->CroppingRegionPlanes[0]<this->CroppingRegionPlanes[1] && 580 * this->CroppingRegionPlanes[2]<this->CroppingRegionPlanes[3] && 581 * this->CroppingRegionPlanes[4]<this->CroppingRegionPlanes[5]) 582 */ 583 virtual void ClipCroppingRegionPlanes(); 584 585 using DataMap = std::unordered_map<int, vtkImageData*>; 586 void SetTransformedInput(vtkImageData*); 587 vtkImageData* FindData(int port, DataMap& container); 588 589 double ClippedCroppingRegionPlanes[6]; 590 591 vtkIdType MaxMemoryInBytes; 592 float MaxMemoryFraction; 593 594 bool ReportProgress; 595 std::vector<int> Ports; 596 std::vector<int> RemovedPorts; 597 DataMap TransformedInputs; 598 599 /** 600 * This is needed only to check if the input data has been changed since the last 601 * Render() call. 602 */ 603 DataMap LastInputs; 604 605 private: 606 vtkGPUVolumeRayCastMapper(const vtkGPUVolumeRayCastMapper&) = delete; 607 void operator=(const vtkGPUVolumeRayCastMapper&) = delete; 608 }; 609 610 #endif 611