/*========================================================================= 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 // 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 void ActivateDrawBuffers(const std::array& 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