/*========================================================================= Program: Visualization Toolkit Module: vtkSmartVolumeMapper.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkSmartVolumeMapper * @brief Adaptive volume mapper * * vtkSmartVolumeMapper is a volume mapper that will delegate to a specific * volume mapper based on rendering parameters and available hardware. Use the * SetRequestedRenderMode() method to control the behavior of the selection. * The following options are available: * * @par vtkSmartVolumeMapper::DefaultRenderMode: * Allow the vtkSmartVolumeMapper to select the best mapper based on * rendering parameters and hardware support. If GPU ray casting is * supported, the vtkGPUVolumeRayCastMapper mapper will be used for * all rendering. If not, then the vtkFixedPointVolumeRayCastMapper * will be used exclusively. This is the default requested render * mode, and is generally the best option. When you use this option, * your volume will always be rendered, but the method used to render * it may vary based on parameters and platform. * * @par vtkSmartVolumeMapper::RayCastRenderMode: * Use the vtkFixedPointVolumeRayCastMapper for both interactive and * still rendering. When you use this option your volume will always * be rendered with the vtkFixedPointVolumeRayCastMapper. * * @par vtkSmartVolumeMapper::GPURenderMode: * Use the vtkGPUVolumeRayCastMapper, if supported, for both * interactive and still rendering. If the GPU ray caster is not * supported (due to hardware limitations or rendering parameters) * then no image will be rendered. Use this option only if you have * already checked for supported based on the current hardware, * number of scalar components, and rendering parameters in the * vtkVolumeProperty. * * @par vtkSmartVolumeMapper::GPURenderMode: * You can adjust the contrast and brightness in the rendered image using the * FinalColorWindow and FinalColorLevel ivars. By default the * FinalColorWindow is set to 1.0, and the FinalColorLevel is set to 0.5, * which applies no correction to the computed image. To apply the window / * level operation to the computer image color, first a Scale and Bias * value are computed: *
 *  scale = 1.0 / this->FinalColorWindow
 *  bias  = 0.5 - this->FinalColorLevel / this->FinalColorWindow
 *  
* To compute a new color (R', G', B', A') from an existing color (R,G,B,A) * for a pixel, the following equation is used: *
 *  R' = R*scale + bias*A
 *  G' = G*scale + bias*A
 *  B' = B*scale + bias*A
 *  A' = A
 *  
* Note that bias is multiplied by the alpha component before adding because * the red, green, and blue component of the color are already pre-multiplied * by alpha. Also note that the window / level operation leaves the alpha * component unchanged - it only adjusts the RGB values. */ #ifndef vtkSmartVolumeMapper_h #define vtkSmartVolumeMapper_h #include "vtkImageReslice.h" // for VTK_RESLICE_NEAREST, VTK_RESLICE_CUBIC #include "vtkRenderingVolumeOpenGL2Module.h" // For export macro #include "vtkVolumeMapper.h" class vtkFixedPointVolumeRayCastMapper; class vtkGPUVolumeRayCastMapper; class vtkImageResample; class vtkMultiBlockVolumeMapper; class vtkOSPRayVolumeInterface; class vtkRenderWindow; class vtkVolume; class vtkVolumeProperty; class vtkImageMagnitude; class VTKRENDERINGVOLUMEOPENGL2_EXPORT vtkSmartVolumeMapper : public vtkVolumeMapper { public: static vtkSmartVolumeMapper* New(); vtkTypeMacro(vtkSmartVolumeMapper, vtkVolumeMapper); void PrintSelf(ostream& os, vtkIndent indent) override; ///@{ /** * Set the final color window. This controls the contrast of * the image. The default value is 1.0. The Window can be * negative (this causes a "negative" effect on the image) * Although Window can be set to 0.0, any value less than * 0.00001 and greater than or equal to 0.0 will be set to * 0.00001, and any value greater than -0.00001 but less * than or equal to 0.0 will be set to -0.00001. * Initial value is 1.0. */ vtkSetMacro(FinalColorWindow, float); ///@} ///@{ /** * Get the final color window. Initial value is 1.0. */ vtkGetMacro(FinalColorWindow, float); ///@} ///@{ /** * Set the final color level. The level controls the * brightness of the image. The final color window will * be centered at the final color level, and together * represent a linear remapping of color values. The * default value for the level is 0.5. */ vtkSetMacro(FinalColorLevel, float); ///@} ///@{ /** * Get the final color level. */ vtkGetMacro(FinalColorLevel, float); ///@} // The possible values for the default and current render mode ivars enum { DefaultRenderMode = 0, RayCastRenderMode = 1, GPURenderMode = 2, OSPRayRenderMode = 3, UndefinedRenderMode = 4, InvalidRenderMode = 5 }; /** * Set the requested render mode. The default is * vtkSmartVolumeMapper::DefaultRenderMode. */ void SetRequestedRenderMode(int mode); /** * Set the requested render mode to vtkSmartVolumeMapper::DefaultRenderMode. * This is the best option for an application that must adapt to different * data types, hardware, and rendering parameters. */ void SetRequestedRenderModeToDefault(); /** * Set the requested render mode to vtkSmartVolumeMapper::RayCastRenderMode. * This option will use software rendering exclusively. This is a good option * if you know there is no hardware acceleration. */ void SetRequestedRenderModeToRayCast(); /** * Set the requested render mode to vtkSmartVolumeMapper::GPURenderMode. * This option will use hardware accelerated rendering exclusively. This is a * good option if you know there is hardware acceleration. */ void SetRequestedRenderModeToGPU(); /** * Set the requested render mode to vtkSmartVolumeMapper::OSPRayRenderMode. * This option will use intel OSPRay to do software rendering exclusively. */ void SetRequestedRenderModeToOSPRay(); ///@{ /** * Get the requested render mode. */ vtkGetMacro(RequestedRenderMode, int); ///@} /** * This will return the render mode used during the previous call to * Render(). */ int GetLastUsedRenderMode(); ///@{ /** * Value passed to the GPU mapper. Ignored by other mappers. * Maximum size of the 3D texture in GPU memory. * Will default to the size computed from the graphics * card. Can be adjusted by the user. * Useful if the automatic detection is defective or missing. */ vtkSetMacro(MaxMemoryInBytes, vtkIdType); vtkGetMacro(MaxMemoryInBytes, vtkIdType); ///@} ///@{ /** * Value passed to the GPU mapper. Ignored by other mappers. * Maximum fraction of the MaxMemoryInBytes that should * be used to hold the texture. Valid values are 0.1 to * 1.0. */ vtkSetClampMacro(MaxMemoryFraction, float, 0.1f, 1.0f); vtkGetMacro(MaxMemoryFraction, float); ///@} ///@{ /** * Set interpolation mode for downsampling (lowres GPU) * (initial value: cubic). */ vtkSetClampMacro(InterpolationMode, int, VTK_RESLICE_NEAREST, VTK_RESLICE_CUBIC); vtkGetMacro(InterpolationMode, int); void SetInterpolationModeToNearestNeighbor(); void SetInterpolationModeToLinear(); void SetInterpolationModeToCubic(); ///@} /** * This method can be used to render a representative view of the input data * into the supplied image given the supplied blending mode, view direction, * and view up vector. */ void CreateCanonicalView(vtkRenderer* ren, vtkVolume* volume, vtkVolume* volume2, vtkImageData* image, int blend_mode, double viewDirection[3], double viewUp[3]); ///@{ /** * If the DesiredUpdateRate of the vtkRenderWindow that caused the Render * falls at or above this rate, the render is considered interactive and * the mapper may be adjusted (depending on the render mode). * Initial value is 1.0. */ vtkSetClampMacro(InteractiveUpdateRate, double, 1.0e-10, 1.0e10); ///@} ///@{ /** * Get the update rate at or above which this is considered an * interactive render. * Initial value is 1.0. */ vtkGetMacro(InteractiveUpdateRate, double); ///@} ///@{ /** * If the InteractiveAdjustSampleDistances flag is enabled, * vtkSmartVolumeMapper interactively sets and resets the * AutoAdjustSampleDistances flag on the internal volume mapper. This flag * along with InteractiveUpdateRate is useful to adjust volume mapper sample * distance based on whether the render is interactive or still. * By default, InteractiveAdjustSampleDistances is enabled. */ vtkSetClampMacro(InteractiveAdjustSampleDistances, vtkTypeBool, 0, 1); vtkGetMacro(InteractiveAdjustSampleDistances, vtkTypeBool); vtkBooleanMacro(InteractiveAdjustSampleDistances, vtkTypeBool); ///@} ///@{ /** * If AutoAdjustSampleDistances is on, the ImageSampleDistance * will be varied to achieve the allocated render time of this * prop (controlled by the desired update rate and any culling in * use). * Note that, this flag is ignored when InteractiveAdjustSampleDistances is * enabled. To explicitly set and use this flag, one must disable * InteractiveAdjustSampleDistances. */ vtkSetClampMacro(AutoAdjustSampleDistances, vtkTypeBool, 0, 1); vtkGetMacro(AutoAdjustSampleDistances, vtkTypeBool); vtkBooleanMacro(AutoAdjustSampleDistances, vtkTypeBool); ///@} ///@{ /** * Set/Get the distance between samples used for rendering * when AutoAdjustSampleDistances is off, or when this mapper * has more than 1 second allocated to it for rendering. * If SampleDistance is negative, it will be computed based on the dataset * spacing. Initial value is -1.0. */ vtkSetMacro(SampleDistance, float); vtkGetMacro(SampleDistance, float); ///@} ///@{ /** * @copydoc vtkGPUVolumeRayCastMapper::SetGlobalIlluminationReach(float) * * This parameter is only used when the underlying mapper * is a vtkGPUVolumeRayCastMapper. */ vtkSetClampMacro(GlobalIlluminationReach, float, 0.0f, 1.0f); vtkGetMacro(GlobalIlluminationReach, float); ///@} ///@{ /** * @copydoc vtkGPUVolumeRayCastMapper::SetVolumetricScatteringBlending(float) * * This parameter is only used when the underlying mapper * is a vtkGPUVolumeRayCastMapper. */ vtkSetClampMacro(VolumetricScatteringBlending, float, 0.0f, 2.0f); vtkGetMacro(VolumetricScatteringBlending, float); ///@} /** * WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE * Initialize rendering for this volume. */ void Render(vtkRenderer*, vtkVolume*) override; /** * WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE * Release any graphics resources that are being consumed by this mapper. * The parameter window could be used to determine which graphic * resources to release. */ void ReleaseGraphicsResources(vtkWindow*) override; ///@{ /** * VectorMode is a special rendering mode for 3-component vectors which makes * use of GPURayCastMapper's independent-component capabilities. In this mode, * a single component in the vector can be selected for rendering. In addition, * the mapper can compute a scalar field representing the magnitude of this vector * using a vtkImageMagnitude object (MAGNITUDE mode). */ enum VectorModeType { DISABLED = -1, MAGNITUDE = 0, COMPONENT = 1, }; void SetVectorMode(int mode); vtkGetMacro(VectorMode, int); vtkSetClampMacro(VectorComponent, int, 0, 3); vtkGetMacro(VectorComponent, int); ///@} //@{ /** * Set/Get the transfer 2D Y axis array */ vtkSetStringMacro(Transfer2DYAxisArray); vtkGetStringMacro(Transfer2DYAxisArray); //@} protected: vtkSmartVolumeMapper(); ~vtkSmartVolumeMapper() override; /** * Connect input of the vtkSmartVolumeMapper to the input of the * internal volume mapper by doing a shallow to avoid memory leaks. * \pre m_exists: m!=0 */ void ConnectMapperInput(vtkVolumeMapper* m); /** * Connect input of the vtkSmartVolumeMapper to the input of the * internal resample filter by doing a shallow to avoid memory leaks. * \pre m_exists: f!=0 */ void ConnectFilterInput(vtkImageResample* f); ///@{ /** * Window / level ivars */ float FinalColorWindow; float FinalColorLevel; ///@} ///@{ /** * GPU mapper-specific memory ivars. */ vtkIdType MaxMemoryInBytes; float MaxMemoryFraction; ///@} /** * Used for downsampling. */ int InterpolationMode; ///@{ /** * The requested render mode is used to compute the current render mode. Note * that the current render mode can be invalid if the requested mode is not * supported. */ int RequestedRenderMode; int CurrentRenderMode; ///@} ///@{ /** * Initialization variables. */ int Initialized; vtkTimeStamp SupportStatusCheckTime; int GPUSupported; int RayCastSupported; int LowResGPUNecessary; ///@} /** * This is the resample filter that may be used if we need to * create a low resolution version of the volume for GPU rendering */ vtkImageResample* GPUResampleFilter; ///@{ /** * This filter is used to compute the magnitude of 3-component data. MAGNITUDE * is one of the supported modes when rendering separately a single independent * component. * * \note * This feature was added specifically for ParaView so it might eventually be * moved into a derived mapper in ParaView. */ vtkImageMagnitude* ImageMagnitude; vtkImageData* InputDataMagnitude; ///@} /** * The initialize method. Called from ComputeRenderMode whenever something * relevant has changed. */ void Initialize(vtkRenderer* ren, vtkVolume* vol); /** * The method that computes the render mode from the requested render mode * based on the support status for each render method. */ void ComputeRenderMode(vtkRenderer* ren, vtkVolume* vol); /** * Expose GPU mapper for additional customization. */ friend class vtkMultiBlockVolumeMapper; vtkGetObjectMacro(GPUMapper, vtkGPUVolumeRayCastMapper); ///@{ /** * The three potential mappers */ vtkGPUVolumeRayCastMapper* GPULowResMapper; vtkGPUVolumeRayCastMapper* GPUMapper; vtkFixedPointVolumeRayCastMapper* RayCastMapper; ///@} /** * We need to keep track of the blend mode we had when we initialized * because we need to reinitialize (and recheck hardware support) if * it changes */ int InitializedBlendMode; /** * The distance between sample points along the ray */ float SampleDistance; /** * Secondary rays ambient/global adjustment coefficient */ float GlobalIlluminationReach = 0.0; /** * Blending coefficient between surfacic and volumetric models in GPU Mapper */ float VolumetricScatteringBlending = 0.0; /** * Set whether or not the sample distance should be automatically calculated * within the internal volume mapper */ vtkTypeBool AutoAdjustSampleDistances; /** * If the DesiredUpdateRate of the vtkRenderWindow causing the Render is at * or above this value, the render is considered interactive. Otherwise it is * considered still. */ double InteractiveUpdateRate; /** * If the InteractiveAdjustSampleDistances flag is enabled, * vtkSmartVolumeMapper interactively sets and resets the * AutoAdjustSampleDistances flag on the internal volume mapper. This flag * along with InteractiveUpdateRate is useful to adjust volume mapper sample * distance based on whether the render is interactive or still. */ vtkTypeBool InteractiveAdjustSampleDistances; ///@{ /** * VectorMode is a special rendering mode for 3-component vectors which makes * use of GPURayCastMapper's independent-component capabilities. In this mode, * a single component in the vector can be selected for rendering. In addition, * the mapper can compute a scalar field representing the magnitude of this vector * using a vtkImageMagnitude object (MAGNITUDE mode). */ int VectorMode; int VectorComponent; vtkTimeStamp MagnitudeUploadTime; ///@} ///@{ /** * Keep a cache of the last input to the mapper so that input data changes can be propagated to * the resample filter and internal mappers. */ vtkDataSet* LastInput; vtkDataSet* LastFilterInput; ///@} /** * Define the array used for the Y axis of transfer 2D. * This is used when the transfer function mode is set to 2D. If unset, the * default is to use the gradient of the scalar. */ char* Transfer2DYAxisArray; private: ///@{ /** * Adjust the GPUMapper's parameters (ColorTable, Weights, etc.) to render * a single component of a dataset. */ void SetupVectorMode(vtkVolume* vol); /** * vtkImageMagnitude is used to compute the norm of the input multi-component * array. vtkImageMagnitude can only process point data, so in the case of cell * data it is first transformed to points. */ void ComputeMagnitudeCellData(vtkDataSet* input, vtkDataArray* arr); void ComputeMagnitudePointData(vtkDataSet* input, vtkDataArray* arr); ///@} vtkSmartVolumeMapper(const vtkSmartVolumeMapper&) = delete; void operator=(const vtkSmartVolumeMapper&) = delete; vtkOSPRayVolumeInterface* OSPRayMapper; }; #endif