You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

399 lines
11 KiB
C++

/*=========================================================================
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 <map> //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<vtkOpenGLFramebufferObject> FBFluidEyeZ;
vtkSmartPointer<vtkOpenGLFramebufferObject> FBThickness;
vtkSmartPointer<vtkOpenGLFramebufferObject> FBFilterThickness;
vtkSmartPointer<vtkOpenGLFramebufferObject> FBCompNormal;
vtkSmartPointer<vtkOpenGLFramebufferObject> 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<vtkOpenGLVertexBufferObjectGroup> 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