/*========================================================================= Program: Visualization Toolkit 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 vtkOpenGLFluidMapper * @brief Render fluid from position data (and color, if available) * * An OpenGL mapper that display fluid volume using a screen space * fluid rendering technique. Thanks to Nghia Truong for the algorihtm * and initial implementation. */ #ifndef vtkOpenGLFluidMapper_h #define vtkOpenGLFluidMapper_h #include "vtkAbstractVolumeMapper.h" #include "vtkOpenGLHelper.h" // used for ivars #include "vtkRenderingOpenGL2Module.h" // For export macro #include "vtkShader.h" // for methods #include "vtkSmartPointer.h" // for ivars #include //for methods class vtkMatrix3x3; class vtkMatrix4x4; class vtkOpenGLFramebufferObject; class vtkOpenGLRenderWindow; class vtkOpenGLState; class vtkOpenGLQuadHelper; class vtkOpenGLVertexBufferObjectGroup; class vtkPolyData; class vtkTextureObject; class VTKRENDERINGOPENGL2_EXPORT vtkOpenGLFluidMapper : public vtkAbstractVolumeMapper { public: static vtkOpenGLFluidMapper* New(); vtkTypeMacro(vtkOpenGLFluidMapper, vtkAbstractVolumeMapper); void PrintSelf(ostream& os, vtkIndent indent) override; //@{ /** * Specify the input data to map. */ void SetInputData(vtkPolyData* in); vtkPolyData* GetInput(); //@} //@{ /** * Turn on/off flag to control whether scalar data is used to color objects. */ vtkSetMacro(ScalarVisibility, bool); vtkGetMacro(ScalarVisibility, bool); vtkBooleanMacro(ScalarVisibility, bool); //@} //@{ /** * Set/Get the particle radius, must be explicitly set by user * To fuse the gaps between particles and obtain a smooth surface, * this parameter need to be slightly larger than the actual particle radius, * (particle radius is the half distance between two consecutive particles in * regular pattern sampling) */ vtkSetMacro(ParticleRadius, float); vtkGetMacro(ParticleRadius, float); //@} //@{ /** * Get/Set the number of filter iterations to filter the depth surface * This is an optional parameter, default value is 3 * Usually set this to around 3-5 * Too many filter iterations will over-smooth the surface */ vtkSetMacro(SurfaceFilterIterations, uint32_t); vtkGetMacro(SurfaceFilterIterations, uint32_t); //@} //@{ /** * Get/Set the number of filter iterations to filter the volume thickness * and particle color This is an optional parameter, default value is 3 */ vtkSetMacro(ThicknessAndVolumeColorFilterIterations, uint32_t); vtkGetMacro(ThicknessAndVolumeColorFilterIterations, uint32_t); //@} //@{ /** * Get/Set the filter radius for smoothing the depth surface * This is an optional parameter, default value is 5 * This is not exactly the radius in pixels, * instead it is just a parameter used for computing the actual filter * radius in the screen space filtering */ vtkSetMacro(SurfaceFilterRadius, uint32_t); vtkGetMacro(SurfaceFilterRadius, uint32_t); //@} //@{ /** * Get/Set the filter radius to filter the volume thickness and particle * color This is an optional parameter, default value is 10 (pixels) */ vtkSetMacro(ThicknessAndVolumeColorFilterRadius, float); vtkGetMacro(ThicknessAndVolumeColorFilterRadius, float); //@} /** * Filter method to filter the depth buffer */ enum FluidSurfaceFilterMethod { BilateralGaussian = 0, NarrowRange, // New filter method can be added here, NumFilterMethods }; //@{ /** * Get/Set the filter method for filtering fluid surface */ vtkSetMacro(SurfaceFilterMethod, vtkOpenGLFluidMapper::FluidSurfaceFilterMethod); vtkGetMacro(SurfaceFilterMethod, vtkOpenGLFluidMapper::FluidSurfaceFilterMethod); //@} /** * Optional parameters, exclusively for narrow range filter * The first parameter is to control smoothing between surface depth values * The second parameter is to control curvature of the surface edges */ void SetNarrowRangeFilterParameters(float lambda, float mu) { this->NRFilterLambda = lambda; this->NRFilterMu = mu; } /** * Optional parameters, exclusively for bilateral gaussian filter * The parameter is for controlling smoothing between surface depth values */ void SetBilateralGaussianFilterParameter(float sigmaDepth) { this->BiGaussFilterSigmaDepth = sigmaDepth; } /** * Display mode for the fluid, default value is TransparentFluidVolume */ enum FluidDisplayMode { UnfilteredOpaqueSurface = 0, FilteredOpaqueSurface, UnfilteredSurfaceNormal, FilteredSurfaceNormal, TransparentFluidVolume, NumDisplayModes }; //@{ /** * Get/Set the display mode */ vtkSetMacro(DisplayMode, vtkOpenGLFluidMapper::FluidDisplayMode); vtkGetMacro(DisplayMode, vtkOpenGLFluidMapper::FluidDisplayMode); //@} //@{ /** * Get/Set the fluid attenuation color * (color that will be absorpted exponentially when going through the fluid * volume) */ vtkSetVector3Macro(AttenuationColor, float); vtkGetVector3Macro(AttenuationColor, float); //@} //@{ /** * Get/Set the fluid surface color if rendered in opaque surface mode * without particle color */ vtkSetVector3Macro(OpaqueColor, float); vtkGetVector3Macro(OpaqueColor, float); //@} //@{ /** * Get/Set the power value for particle color if input data has particle * color Default value is 0.1, and can be set to any non-negative number The * particle color is then recomputed as newColor = pow(oldColor, power) * * scale */ vtkSetMacro(ParticleColorPower, float); vtkGetMacro(ParticleColorPower, float); //@} //@{ /** * Get/Set the scale value for particle color if input data has particle * color Default value is 1.0, and can be set to any non-negative number The * particle color is then recomputed as newColor = pow(oldColor, power) * * scale */ vtkSetMacro(ParticleColorScale, float); vtkGetMacro(ParticleColorScale, float); //@} //@{ /** * Get/Set the fluid volume attenuation scale, which will be multiplied * with attennuation color Default value is 1.0, and can be set to any * non-negative number The larger attennuation scale, the darker fluid * color */ vtkSetMacro(AttenuationScale, float); vtkGetMacro(AttenuationScale, float); //@} //@{ /** * Get/Set the fluid surface additional reflection scale This value is in * [0, 1], which 0 means using the reflection color computed from fresnel * equation, and 1 means using reflection color as [1, 1, 1] Default value * is 0 */ vtkSetMacro(AdditionalReflection, float); vtkGetMacro(AdditionalReflection, float); //@} //@{ /** * Get/Set the scale value for refraction This is needed for tweak * refraction of volumes with different size scales For example, fluid * volume having diameter of 100.0 will refract light much more than * volume with diameter 1.0 This value is in [0, 1], default value is 1.0 */ vtkSetMacro(RefractionScale, float); vtkGetMacro(RefractionScale, float); //@} //@{ /** * Get/Set the fluid refraction index. The default value is 1.33 (water) */ vtkSetMacro(RefractiveIndex, float); vtkGetMacro(RefractiveIndex, float); //@} /** * This calls RenderPiece */ void Render(vtkRenderer* ren, vtkVolume* vol) override; /** * Release graphics resources and ask components to release their own * resources. * \pre w_exists: w!=0 */ void ReleaseGraphicsResources(vtkWindow* w) override; protected: vtkOpenGLFluidMapper(); ~vtkOpenGLFluidMapper() override; /** * Perform string replacements on the shader templates */ void UpdateDepthThicknessColorShaders( vtkOpenGLHelper& glHelper, vtkRenderer* renderer, vtkVolume* vol); /** * Set the shader parameters related to the actor/mapper/camera */ void SetDepthThicknessColorShaderParameters( vtkOpenGLHelper& glHelper, vtkRenderer* renderer, vtkVolume* vol); /** * Setup the texture buffers */ void SetupBuffers(vtkOpenGLRenderWindow* const renderWindow); /** * Render the fluid particles */ void RenderParticles(vtkRenderer* renderer, vtkVolume* vol); // Public parameters, their usage are stated at their Get/Set functions // ======>>>>> float ParticleRadius = 1.0f; FluidSurfaceFilterMethod SurfaceFilterMethod = FluidSurfaceFilterMethod::NarrowRange; uint32_t SurfaceFilterIterations = 3u; uint32_t SurfaceFilterRadius = 5u; float NRFilterLambda = 10.0f; float NRFilterMu = 1.0f; float BiGaussFilterSigmaDepth = 10.0f; uint32_t ThicknessAndVolumeColorFilterIterations = 3u; uint32_t ThicknessAndVolumeColorFilterRadius = 10u; FluidDisplayMode DisplayMode = FluidDisplayMode::TransparentFluidVolume; float OpaqueColor[3]{ 0.0f, 0.0f, 0.95f }; float AttenuationColor[3]{ 0.5f, 0.2f, 0.05f }; float ParticleColorPower = 0.1f; float ParticleColorScale = 1.0f; float AttenuationScale = 1.0f; float AdditionalReflection = 0.0f; float RefractionScale = 1.0f; float RefractiveIndex = 1.33f; bool ScalarVisibility = false; bool InDepthPass = true; // Private parameters ======>>>>> // Indicate that the input data has a color buffer bool HasVertexColor = false; // Cache viewport dimensions int ViewportX; int ViewportY; int ViewportWidth; int ViewportHeight; // Cache camera parameters vtkMatrix4x4* CamWCVC; vtkMatrix3x3* CamInvertedNorms; vtkMatrix4x4* CamVCDC; vtkMatrix4x4* CamWCDC; vtkMatrix4x4* CamDCVC; vtkTypeBool CamParallelProjection; // Frame buffers vtkSmartPointer FBFluidEyeZ; vtkSmartPointer FBThickness; vtkSmartPointer FBFilterThickness; vtkSmartPointer FBCompNormal; vtkSmartPointer FBFilterDepth; // Screen quad render vtkOpenGLQuadHelper* QuadFluidDepthFilter[NumFilterMethods]{ nullptr, nullptr }; vtkOpenGLQuadHelper* QuadThicknessFilter = nullptr; vtkOpenGLQuadHelper* QuadFluidNormal = nullptr; vtkOpenGLQuadHelper* QuadFinalBlend = nullptr; // The VBO and its layout for rendering particles vtkSmartPointer VBOs; vtkTimeStamp VBOBuildTime; // When was the OpenGL VBO updated? vtkOpenGLHelper GLHelperDepthThickness; // Texture buffers enum TextureBuffers { OpaqueZ = 0, OpaqueRGBA, FluidZ, FluidEyeZ, SmoothedFluidEyeZ, FluidThickness, SmoothedFluidThickness, FluidNormal, NumTexBuffers }; // These are optional texture buffers enum OptionalTextureBuffers { Color = 0, SmoothedColor, NumOptionalTexBuffers }; vtkTextureObject* TexBuffer[NumTexBuffers]; vtkTextureObject* OptionalTexBuffer[NumOptionalTexBuffers]; vtkMatrix4x4* TempMatrix4; private: vtkOpenGLFluidMapper(const vtkOpenGLFluidMapper&) = delete; void operator=(const vtkOpenGLFluidMapper&) = delete; }; #endif