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.
283 lines
8.9 KiB
C++
283 lines
8.9 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkDualDepthPeelingPass.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 vtkDualDepthPeelingPass
|
|
* @brief Implements the dual depth peeling algorithm.
|
|
*
|
|
*
|
|
* Dual depth peeling is an augmentatation of the standard depth peeling
|
|
* algorithm that peels two layers (front and back) for each render pass. The
|
|
* technique is described in "Order independent transparency with dual depth
|
|
* peeling" (February 2008) by L. Bavoil, K. Myers.
|
|
*
|
|
* This algorithm has been extended to also peel volumetric data along with
|
|
* translucent geometry. To use this feature, set VolumetricPass to an
|
|
* appropriate RenderPass (usually vtkVolumetricPass).
|
|
*
|
|
* The pass occurs in several stages:
|
|
*
|
|
* 1. Copy the current (opaque geometry) depth buffer into a texture.
|
|
* 2. Initialize the min-max depth buffer from the opaque depth texture and the
|
|
* translucent geometry.
|
|
* 3. Peel the nearest and farthest fragments:
|
|
* 3a. Blend fragments that match the nearest depth of the min-max depth buffer
|
|
* into the front buffer.
|
|
* 3b. Write the far depth fragments into a temporary buffer.
|
|
* 3c. Extract the next set of min/max depth values for the next peel.
|
|
* 3d. Blend the temporary far fragment texture (3b) into an accumulation
|
|
* texture.
|
|
* 3e. Go back to 3a and repeat until the maximum number of peels is met, or
|
|
* the desired occlusion ratio is satisfied.
|
|
* 4. If the occlusion ratio != 0 (i.e. we hit the maximum number of peels
|
|
* before finishing), alpha blend the remaining fragments in-between the
|
|
* near and far accumulation textures.
|
|
* 5. Blend all accumulation buffers over the opaque color buffer to produce the
|
|
* final image.
|
|
*/
|
|
|
|
#ifndef vtkDualDepthPeelingPass_h
|
|
#define vtkDualDepthPeelingPass_h
|
|
|
|
#include "vtkDepthPeelingPass.h"
|
|
#include "vtkRenderingOpenGL2Module.h" // For export macro
|
|
|
|
#include <array> // For std::array!
|
|
|
|
class vtkOpenGLFramebufferObject;
|
|
class vtkOpenGLQuadHelper;
|
|
class vtkOpenGLVertexArrayObject;
|
|
class vtkRenderTimerLog;
|
|
class vtkShaderProgram;
|
|
class vtkTextureObject;
|
|
|
|
class VTKRENDERINGOPENGL2_EXPORT vtkDualDepthPeelingPass : public vtkDepthPeelingPass
|
|
{
|
|
public:
|
|
static vtkDualDepthPeelingPass* New();
|
|
vtkTypeMacro(vtkDualDepthPeelingPass, vtkDepthPeelingPass);
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
|
|
|
void Render(const vtkRenderState* s) override;
|
|
void ReleaseGraphicsResources(vtkWindow* w) override;
|
|
|
|
//@{
|
|
/**
|
|
* Delegate for rendering the volumetric geometry, if needed.
|
|
* It is usually set to a vtkVolumetricPass.
|
|
* Initial value is a NULL pointer.
|
|
*/
|
|
vtkGetObjectMacro(VolumetricPass, vtkRenderPass) virtual void SetVolumetricPass(
|
|
vtkRenderPass* volumetricPass);
|
|
//@}
|
|
|
|
// vtkOpenGLRenderPass virtuals:
|
|
bool PreReplaceShaderValues(std::string& vertexShader, std::string& geometryShader,
|
|
std::string& fragmentShader, vtkAbstractMapper* mapper, vtkProp* prop) override;
|
|
bool PostReplaceShaderValues(std::string& vertexShader, std::string& geometryShader,
|
|
std::string& fragmentShader, vtkAbstractMapper* mapper, vtkProp* prop) override;
|
|
bool SetShaderParameters(vtkShaderProgram* program, vtkAbstractMapper* mapper, vtkProp* prop,
|
|
vtkOpenGLVertexArrayObject* VAO = nullptr) override;
|
|
vtkMTimeType GetShaderStageMTime() override;
|
|
|
|
protected:
|
|
bool PostReplaceTranslucentShaderValues(std::string& vertexShader, std::string& geometryShader,
|
|
std::string& fragmentShader, vtkAbstractMapper* mapper, vtkProp* prop);
|
|
bool PreReplaceVolumetricShaderValues(std::string& vertexShader, std::string& geometryShader,
|
|
std::string& fragmentShader, vtkAbstractMapper* mapper, vtkProp* prop);
|
|
bool SetTranslucentShaderParameters(vtkShaderProgram* program, vtkAbstractMapper* mapper,
|
|
vtkProp* prop, vtkOpenGLVertexArrayObject* VAO);
|
|
bool SetVolumetricShaderParameters(vtkShaderProgram* program, vtkAbstractMapper* mapper,
|
|
vtkProp* prop, vtkOpenGLVertexArrayObject* VAO);
|
|
|
|
// Name the textures used by this render pass. These are indexes into
|
|
// this->Textures
|
|
enum TextureName
|
|
{
|
|
BackTemp = 0, // RGBA8 back-to-front peeling buffer
|
|
Back, // RGBA8 back-to-front accumulation buffer
|
|
FrontA, // RGBA8 front-to-back accumulation buffer
|
|
FrontB, // RGBA8 front-to-back accumulation buffer
|
|
DepthA, // RG32F min-max depth buffer
|
|
DepthB, // RG32F min-max depth buffer
|
|
OpaqueDepth, // Stores the depth map from the opaque passes
|
|
|
|
NumberOfTextures
|
|
};
|
|
|
|
// The stages of this multipass render pass:
|
|
enum ShaderStage
|
|
{
|
|
InitializingDepth,
|
|
Peeling,
|
|
AlphaBlending,
|
|
|
|
NumberOfPasses,
|
|
Inactive = -1,
|
|
};
|
|
|
|
enum PeelType
|
|
{
|
|
TranslucentPeel,
|
|
VolumetricPeel
|
|
};
|
|
|
|
vtkDualDepthPeelingPass();
|
|
~vtkDualDepthPeelingPass() override;
|
|
|
|
void SetCurrentStage(ShaderStage stage);
|
|
vtkSetMacro(CurrentPeelType, PeelType);
|
|
|
|
/**
|
|
* Release all FBOs and textures.
|
|
*/
|
|
void FreeGLObjects();
|
|
|
|
/**
|
|
* Render the translucent pass geometry, counting number of render calls.
|
|
*/
|
|
void RenderTranslucentPass();
|
|
|
|
/**
|
|
* Render any volumetric geometry.
|
|
*/
|
|
void RenderVolumetricPass();
|
|
|
|
bool IsRenderingVolumes();
|
|
|
|
/**
|
|
* Allocate and configure FBOs and textures.
|
|
*/
|
|
void Initialize(const vtkRenderState* state);
|
|
|
|
//@{
|
|
/**
|
|
* Initialize helpers.
|
|
*/
|
|
void InitColorTexture(vtkTextureObject* tex, const vtkRenderState* s);
|
|
void InitDepthTexture(vtkTextureObject* tex, const vtkRenderState* s);
|
|
void InitOpaqueDepthTexture(vtkTextureObject* tex, const vtkRenderState* s);
|
|
void InitFramebuffer(const vtkRenderState* s);
|
|
//@}
|
|
|
|
/**
|
|
* Bind and activate draw buffers.
|
|
* @{
|
|
*/
|
|
void ActivateDrawBuffer(TextureName id) { this->ActivateDrawBuffers(&id, 1); }
|
|
template <size_t NumTextures>
|
|
void ActivateDrawBuffers(const std::array<TextureName, NumTextures>& a)
|
|
{
|
|
this->ActivateDrawBuffers(a.data(), a.size());
|
|
}
|
|
void ActivateDrawBuffers(const TextureName* ids, size_t numTextures);
|
|
/**@}*/
|
|
|
|
/**
|
|
* Fill textures with initial values, bind the framebuffer.
|
|
*/
|
|
void Prepare();
|
|
|
|
void InitializeOcclusionQuery();
|
|
void CopyOpaqueDepthBuffer();
|
|
void InitializeDepth();
|
|
|
|
void PeelVolumesOutsideTranslucentRange();
|
|
|
|
bool PeelingDone();
|
|
|
|
/**
|
|
* Render the scene to produce the next set of peels.
|
|
*/
|
|
void Peel();
|
|
|
|
// Depending on whether we're handling volumes or not, we'll initialize the
|
|
// front destination buffer by either clearing it or copying the last peel's
|
|
// output into it.
|
|
void PrepareFrontDestination();
|
|
void ClearFrontDestination();
|
|
void CopyFrontSourceToFrontDestination();
|
|
|
|
void InitializeTargetsForTranslucentPass();
|
|
void InitializeTargetsForVolumetricPass();
|
|
|
|
void PeelTranslucentGeometry();
|
|
void PeelVolumetricGeometry();
|
|
|
|
void BlendBackBuffer();
|
|
|
|
void StartTranslucentOcclusionQuery();
|
|
void EndTranslucentOcclusionQuery();
|
|
|
|
void StartVolumetricOcclusionQuery();
|
|
void EndVolumetricOcclusionQuery();
|
|
|
|
/**
|
|
* Swap the src/dest render targets:
|
|
*/
|
|
void SwapFrontBufferSourceDest();
|
|
void SwapDepthBufferSourceDest();
|
|
|
|
void Finalize();
|
|
|
|
void AlphaBlendRender();
|
|
|
|
void BlendFinalImage();
|
|
void DeleteOcclusionQueryIds();
|
|
|
|
vtkRenderTimerLog* Timer;
|
|
vtkRenderPass* VolumetricPass;
|
|
const vtkRenderState* RenderState;
|
|
|
|
vtkOpenGLQuadHelper* CopyColorHelper;
|
|
vtkOpenGLQuadHelper* CopyDepthHelper;
|
|
vtkOpenGLQuadHelper* BackBlendHelper;
|
|
vtkOpenGLQuadHelper* BlendHelper;
|
|
|
|
vtkTextureObject* Textures[NumberOfTextures];
|
|
|
|
TextureName FrontSource; // The current front source buffer
|
|
TextureName FrontDestination; // The current front destination buffer
|
|
TextureName DepthSource; // The current depth source buffer
|
|
TextureName DepthDestination; // The current depth destination buffer
|
|
|
|
ShaderStage CurrentStage;
|
|
PeelType CurrentPeelType;
|
|
vtkTimeStamp CurrentStageTimeStamp;
|
|
|
|
bool LastPeelHadVolumes;
|
|
int CurrentPeel;
|
|
unsigned int TranslucentOcclusionQueryId;
|
|
unsigned int TranslucentWrittenPixels;
|
|
unsigned int VolumetricOcclusionQueryId;
|
|
unsigned int VolumetricWrittenPixels;
|
|
unsigned int OcclusionThreshold;
|
|
|
|
int TranslucentRenderCount; // Debug info, counts number of geometry passes.
|
|
int VolumetricRenderCount; // Debug info, counts number of volumetric passes.
|
|
|
|
// Cached state:
|
|
bool SaveScissorTestState;
|
|
int CullFaceMode;
|
|
bool CullFaceEnabled;
|
|
bool DepthTestEnabled;
|
|
|
|
private:
|
|
vtkDualDepthPeelingPass(const vtkDualDepthPeelingPass&) = delete;
|
|
void operator=(const vtkDualDepthPeelingPass&) = delete;
|
|
};
|
|
|
|
#endif // vtkDualDepthPeelingPass_h
|