From: Nikolay Gavrilov Date: Thu, 13 Oct 2022 13:27:50 +0000 (+0300) Subject: 0027223: Visualization, Ray Tracing - add support of clipping planes X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=54283ac5c3aed7b8708ec515f023fde11f0c1510;p=occt.git 0027223: Visualization, Ray Tracing - add support of clipping planes --- diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx index 8138cd165f..7f4bf30689 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -101,7 +101,7 @@ public: } //! Pass clip planes to the associated graphic driver structure - void SetClipPlanes (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes) { myClipPlanes = thePlanes; } + virtual void SetClipPlanes (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes) { myClipPlanes = thePlanes; } //! @return bounding box of this presentation const Graphic3d_BndBox3d& BoundingBox() const diff --git a/src/OpenGl/OpenGl_SceneGeometry.cxx b/src/OpenGl/OpenGl_SceneGeometry.cxx index a8ceb444b2..7d321655fe 100644 --- a/src/OpenGl/OpenGl_SceneGeometry.cxx +++ b/src/OpenGl/OpenGl_SceneGeometry.cxx @@ -521,6 +521,18 @@ Standard_Boolean OpenGl_RaytraceGeometry::UpdateTextureHandles (const Handle(Ope return Standard_True; } +// ======================================================================= +// function : OpenGl_RaytraceClipPlanes +// purpose : Creates new set of clipping planes +// ======================================================================= +OpenGl_RaytraceClipPlanes::OpenGl_RaytraceClipPlanes() +{ + for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < MAX_PLANE_NUMBER; ++aPlaneIdx) + { + myClipPlanes[aPlaneIdx * 2] = BVH_Vec4f(-1.f, -1.f, -1.f, -1.f); + } +} + namespace OpenGl_Raytrace { // ======================================================================= diff --git a/src/OpenGl/OpenGl_SceneGeometry.hxx b/src/OpenGl/OpenGl_SceneGeometry.hxx index 05705962f5..a1821017df 100644 --- a/src/OpenGl/OpenGl_SceneGeometry.hxx +++ b/src/OpenGl/OpenGl_SceneGeometry.hxx @@ -169,6 +169,133 @@ private: }; +//! Set of clipping planes specific for OpenGL primitive array. +class OpenGl_RaytraceClipPlanes +{ +public: + + //! Maximum number of clipping planes used in ray-tracing for each + //! OpenGL primitive array. This is not implementation restriction, + //! but it is reasonable to limit max number of planes in order to + //! simplify GLSL data representation. + static const Standard_Integer MAX_PLANE_NUMBER = 8; + + //! State of clipping plane. + enum ClipPlaneState { + + CLIP_PLANE_OFF = -1, //!< plane is deactivated + CLIP_PLANE_VIEW = 0, //!< plane is in view space + CLIP_PLANE_WORLD = 1 //!< plane is in world space + }; + + //! Wrapper for clipping plane configuration. + class ClipPlane + { + public: + + //! Creates new clipping plane wrapper. + ClipPlane(BVH_Vec4f& theSettings, + BVH_Vec4f& theEquation) : mySettings(theSettings), + myEquation(theEquation) {} + + //! Sets 4D equation vector for clipping plane. + void SetEquation(const BVH_Vec4d& theEquation, const ClipPlaneState theState = CLIP_PLANE_WORLD) + { + for (Standard_Integer anIndex = 0; anIndex < 4; ++anIndex) + { + myEquation[anIndex] = static_cast (theEquation[anIndex]); + } + + SetState(theState); + } + + //! Returns state of clipping plane. + ClipPlaneState State() + { + return static_cast ((int)mySettings.x()); + } + + //! Sets state of clipping plane. + void SetState(const ClipPlaneState theState) + { + mySettings.x() = static_cast (theState); + } + + private: + + //! Settings of clipping plane. + BVH_Vec4f& mySettings; + + //! 4D equation vector of clipping plane. + BVH_Vec4f& myEquation; + }; + +public: + + //! Creates new set of clipping planes. + OpenGl_RaytraceClipPlanes(); + + //! Returns clipping plane for the given index. + ClipPlane operator[] (const Standard_Integer theIndex) + { + return ClipPlane(myClipPlanes[theIndex * 2 + 0], + myClipPlanes[theIndex * 2 + 1]); + } + + //! Returns packed (serialized) representation of clipping planes set. + const Standard_ShortReal* Packed() + { + return reinterpret_cast (this); + } + +private: + + //! Serialized clipping planes storage. + BVH_Vec4f myClipPlanes[MAX_PLANE_NUMBER * 2]; + +}; + +//! Stores transform properties of ray-tracing object. +class OpenGl_RaytraceTransform : public BVH_Transform +{ +public: + + //! Value of invalid clipping plane set. + static const Standard_Integer NO_CLIPPING = -1; + +public: + + //! Creates new identity transformation. + OpenGl_RaytraceTransform() : BVH_Transform() + { + myClipSetID = NO_CLIPPING; // no clipping by default + } + + //! Creates new transformation with specified matrix. + OpenGl_RaytraceTransform(const BVH_Mat4f& theTransform) : BVH_Transform(theTransform) + { + myClipSetID = NO_CLIPPING; // no clipping by default + } + + //! Returns ID of associated set of clipping planes. + Standard_Integer ClipSetID() const + { + return myClipSetID; + } + + //! Sets ID of associated set of clipping planes. + void SetClipSetID(const Standard_Integer theClipSetID) + { + myClipSetID = theClipSetID; + } + +protected: + + //! ID of associated set of clipping planes. + Standard_Integer myClipSetID; + +}; + //! Stores geometry of ray-tracing scene. class OpenGl_RaytraceGeometry : public BVH_Geometry { @@ -192,6 +319,10 @@ public: //! Array of 'front' material properties. std::vector > Materials; + + //! Array of sets of clipping plane parameters. + std::vector > ClipPlanes; //! Global ambient from all light sources. BVH_Vec4f Ambient; diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index d5c3c5270b..798ca89b2f 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -236,6 +236,20 @@ Standard_Boolean OpenGl_Structure::IsRaytracable() const && myInstancedStructure->IsRaytracable(); } +// ======================================================================= +// function : SetClipPlanes +// purpose : +// ======================================================================= +void OpenGl_Structure::SetClipPlanes(const Handle(Graphic3d_SequenceOfHClipPlane)&thePlanes) +{ + Graphic3d_CStructure::SetClipPlanes(thePlanes); + + if (IsRaytracable()) + { + ++myModificationState; + } +} + // ======================================================================= // function : UpdateRaytracableState // purpose : diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index b770323783..bf1eacac39 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -132,6 +132,9 @@ protected: //! Updates ray-tracable status for structure and its parents. void UpdateStateIfRaytracable (const Standard_Boolean toCheck = Standard_True) const; + //! Pass clip planes to the associated graphic driver structure + void SetClipPlanes(const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes); + //! Renders groups of structure without applying any attributes (i.e. transform, material etc). //! @param theWorkspace current workspace //! @param theHasClosed flag will be set to TRUE if structure contains at least one group of closed primitives diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 17768a06d1..57fe01cb1f 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -574,6 +574,7 @@ protected: //! @name data types related to ray-tracing OpenGl_RT_uSceneEps, OpenGl_RT_uLightAmbnt, OpenGl_RT_uLightCount, + OpenGl_RT_uNbClipPlanes, // background params OpenGl_RT_uBackColorTop, @@ -1019,6 +1020,8 @@ protected: //! @name fields related to ray-tracing Handle(OpenGl_TextureBuffer) myRaytraceMaterialTexture; //! Texture buffer of light source properties. Handle(OpenGl_TextureBuffer) myRaytraceLightSrcTexture; + //! Texture buffer of clipping planes parameters. + Handle(OpenGl_TextureBuffer) myRaytraceClippingTexture; //! 1st framebuffer (FBO) to perform adaptive FSAA. //! Used in compatibility mode (no adaptive sampling). diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index 299b7b014b..b49c256078 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -65,11 +65,12 @@ namespace static const Graphic3d_TextureUnit OpenGl_RT_RaytraceMaterialTexture = Graphic3d_TextureUnit_9; static const Graphic3d_TextureUnit OpenGl_RT_RaytraceLightSrcTexture = Graphic3d_TextureUnit_10; + static const Graphic3d_TextureUnit OpenGl_RT_RaytraceClippingTexture = Graphic3d_TextureUnit_11; - static const Graphic3d_TextureUnit OpenGl_RT_FsaaInputTexture = Graphic3d_TextureUnit_11; - static const Graphic3d_TextureUnit OpenGl_RT_PrevAccumTexture = Graphic3d_TextureUnit_12; + static const Graphic3d_TextureUnit OpenGl_RT_FsaaInputTexture = Graphic3d_TextureUnit_12; + static const Graphic3d_TextureUnit OpenGl_RT_PrevAccumTexture = Graphic3d_TextureUnit_13; - static const Graphic3d_TextureUnit OpenGl_RT_RaytraceDepthTexture = Graphic3d_TextureUnit_13; + static const Graphic3d_TextureUnit OpenGl_RT_RaytraceDepthTexture = Graphic3d_TextureUnit_14; } // ======================================================================= @@ -512,6 +513,47 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure* const Handle(TopLoc_Datum3D)& theTrsf, const Handle(OpenGl_Context)& theGlContext) { + // ID of clipping plane set + Standard_Integer aClipSetID = OpenGl_RaytraceTransform::NO_CLIPPING; + // Collect clipping planes of structure scope + if (!theStructure->ClipPlanes().IsNull()) + //if (!theStructure->ClipPlanes()->IsEmpty()) + { + NCollection_Handle aUserPlanes; + + for (Graphic3d_SequenceOfHClipPlane::Iterator aClipIter(theStructure->ClipPlanes()); aClipIter.More(); aClipIter.Next()) + { + const Handle(Graphic3d_ClipPlane)& aClipPlane = aClipIter.Value(); + + if (aClipPlane->IsOn()) + { + if (aUserPlanes.IsNull()) + { + aUserPlanes = new Graphic3d_SequenceOfHClipPlane(); + } + + aUserPlanes->Append(aClipPlane); + } + } + + if (!aUserPlanes.IsNull()) + { + myRaytraceGeometry.ClipPlanes.push_back(OpenGl_RaytraceClipPlanes()); + + Standard_Integer aPlaneIdx = 0; + for (Graphic3d_SequenceOfHClipPlane::Iterator aClipIter(*aUserPlanes); aClipIter.More(); aClipIter.Next(), ++aPlaneIdx) + { + if (myRaytraceGeometry.ClipPlanes.size() >= OpenGl_RaytraceClipPlanes::MAX_PLANE_NUMBER) + { + break; + } + myRaytraceGeometry.ClipPlanes.back()[aPlaneIdx].SetEquation(aClipIter.Value()->GetEquation()); + } + + aClipSetID = static_cast (myRaytraceGeometry.ClipPlanes.size() - 1); + } + } + OpenGl_Mat4 aMat4; for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->Groups()); aGroupIter.More(); aGroupIter.Next()) { @@ -551,13 +593,19 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure* if (aSetIter != myArrayToTrianglesMap.end()) { OpenGl_TriangleSet* aSet = aSetIter->second; - opencascade::handle > aTransform = new BVH_Transform(); + OpenGl_RaytraceTransform* aTransform = new OpenGl_RaytraceTransform; + if (!theTrsf.IsNull()) { theTrsf->Trsf().GetMat4 (aMat4); aTransform->SetTransform (aMat4); } + if (aClipSetID != OpenGl_RaytraceTransform::NO_CLIPPING) + { + aTransform->SetClipSetID(aClipSetID); + } + aSet->SetProperties (aTransform); if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID) { @@ -568,13 +616,19 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure* { if (Handle(OpenGl_TriangleSet) aSet = addRaytracePrimitiveArray (aPrimArray, aMatID, 0)) { - opencascade::handle > aTransform = new BVH_Transform(); + OpenGl_RaytraceTransform* aTransform = new OpenGl_RaytraceTransform; + if (!theTrsf.IsNull()) { theTrsf->Trsf().GetMat4 (aMat4); aTransform->SetTransform (aMat4); } + if (aClipSetID != OpenGl_RaytraceTransform::NO_CLIPPING) + { + aTransform->SetClipSetID(aClipSetID); + } + aSet->SetProperties (aTransform); myRaytraceGeometry.Objects().Append (aSet); } @@ -1669,6 +1723,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture); aShaderProgram->SetSampler (theGlContext, "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture); + aShaderProgram->SetSampler(theGlContext, + "uRaytraceClippingTexture", OpenGl_RT_RaytraceClippingTexture); if (anIndex == 1) { @@ -1713,6 +1769,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS aShaderProgram->GetUniformLocation (theGlContext, "uLightCount"); myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] = aShaderProgram->GetUniformLocation (theGlContext, "uGlobalAmbient"); + myUniformLocations[anIndex][OpenGl_RT_uNbClipPlanes] = + aShaderProgram->GetUniformLocation(theGlContext, "uNbClipPlanes"); myUniformLocations[anIndex][OpenGl_RT_uFsaaOffset] = aShaderProgram->GetUniformLocation (theGlContext, "uFsaaOffset"); @@ -1850,6 +1908,7 @@ void OpenGl_View::releaseRaytraceResources (const Handle(OpenGl_Context)& theGlC nullifyResource (theGlContext, myRaytraceLightSrcTexture); nullifyResource (theGlContext, myRaytraceMaterialTexture); + nullifyResource (theGlContext, myRaytraceClippingTexture); myRaytraceGeometry.ReleaseResources (theGlContext); @@ -2190,7 +2249,23 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)& return Standard_False; } } - + + ///////////////////////////////////////////////////////////////////////////// + // Create clip planes buffer + + if (myRaytraceClippingTexture.IsNull()) // create clipping planes buffer + { + myRaytraceClippingTexture = new OpenGl_TextureBuffer; + + if (!myRaytraceClippingTexture->Create(theGlContext)) + { +#ifdef RAY_TRACE_PRINT_INFO + std::cout << "Error: Failed to create buffer for clip plane data" << std::endl; +#endif + return Standard_False; + } + } + ///////////////////////////////////////////////////////////////////////////// // Write transform buffer @@ -2203,11 +2278,16 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)& OpenGl_TriangleSet* aTriangleSet = dynamic_cast ( myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->()); - const BVH_Transform* aTransform = dynamic_cast* > (aTriangleSet->Properties().get()); + const OpenGl_RaytraceTransform* aTransform = dynamic_cast (aTriangleSet->Properties().operator->()); + Standard_ASSERT_RETURN (aTransform != NULL, "OpenGl_TriangleSet does not contain transform", Standard_False); aNodeTransforms[anElemIndex] = aTransform->Inversed(); + + // Note: write clip plane ID in last matrix component, because + // the last matrix row is not used for transformation purposes + aNodeTransforms[anElemIndex].SetValue(3, 3, aTransform->ClipSetID()); } aResult &= mySceneTransformTexture->Init (theGlContext, 4, @@ -2372,6 +2452,23 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)& } } + ///////////////////////////////////////////////////////////////////////////// + // Write clip planes buffer + + if (myRaytraceGeometry.ClipPlanes.size() != 0) + { + aResult &= myRaytraceClippingTexture->Init(theGlContext, 4, + GLsizei(myRaytraceGeometry.ClipPlanes.size() * 16), myRaytraceGeometry.ClipPlanes.front().Packed()); + + if (!aResult) + { +#ifdef RAY_TRACE_PRINT_INFO + std::cout << "Error: Failed to upload clipping planes buffer" << std::endl; +#endif + return Standard_False; + } + } + myIsRaytraceDataValid = myRaytraceGeometry.Objects().Size() != 0; #ifdef RAY_TRACE_PRINT_INFO @@ -2646,6 +2743,9 @@ Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer the theProgram->SetUniform (theGlContext, myUniformLocations[theProgramId][OpenGl_RT_uLightCount], aLightSourceBufferSize); + theProgram->SetUniform (theGlContext, + myUniformLocations[theProgramId][OpenGl_RT_uNbClipPlanes], (int)myRaytraceGeometry.ClipPlanes.size()); + // Set array of 64-bit texture handles if (theGlContext->arbTexBindless != NULL && myRaytraceGeometry.HasTextures()) { @@ -2779,6 +2879,7 @@ void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlConte mySceneTransformTexture ->BindTexture (theGlContext, OpenGl_RT_SceneTransformTexture); myRaytraceMaterialTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceMaterialTexture); myRaytraceLightSrcTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceLightSrcTexture); + myRaytraceClippingTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceClippingTexture); } // ======================================================================= @@ -2797,6 +2898,7 @@ void OpenGl_View::unbindRaytraceTextures (const Handle(OpenGl_Context)& theGlCon mySceneTransformTexture ->UnbindTexture (theGlContext, OpenGl_RT_SceneTransformTexture); myRaytraceMaterialTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceMaterialTexture); myRaytraceLightSrcTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceLightSrcTexture); + myRaytraceClippingTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceClippingTexture); theGlContext->core15fwd->glActiveTexture (GL_TEXTURE0); } diff --git a/src/Shaders/RaytraceBase.fs b/src/Shaders/RaytraceBase.fs index e31b56e6bb..41fc5da389 100644 --- a/src/Shaders/RaytraceBase.fs +++ b/src/Shaders/RaytraceBase.fs @@ -70,6 +70,8 @@ uniform isamplerBuffer uGeometryTriangTexture; uniform samplerBuffer uRaytraceMaterialTexture; //! Texture buffer of light source properties. uniform samplerBuffer uRaytraceLightSrcTexture; +//! Texture buffer of clipping planes properties. +uniform samplerBuffer uRaytraceClippingTexture; #ifdef BACKGROUND_CUBEMAP //! Environment cubemap texture. @@ -87,6 +89,8 @@ uniform samplerBuffer uRaytraceLightSrcTexture; uniform int uLightCount; //! Intensity of global ambient light. uniform vec4 uGlobalAmbient; +//! Number of clipping planes. +uniform int uNbClipPlanes; //! Enables/disables hard shadows. uniform int uShadowsEnabled; @@ -460,6 +464,12 @@ struct SSubTree #define MATERIAL_TRS2(index) (19 * index + 8) #define MATERIAL_TRS3(index) (19 * index + 9) +#define IS_PLANE_ACTIVE(params) (params.x != -1.F) +#define IS_PLANE_HIDDEN(params) (params.x == -1.F) + +#define PLANE_SETTINGS(trsf, index) (16 * int(trsf.w) + 2 * index + 0) +#define PLANE_EQUATION(trsf, index) (16 * int(trsf.w) + 2 * index + 1) + #define TRS_OFFSET(treelet) treelet.SubData.x #define BVH_OFFSET(treelet) treelet.SubData.y #define VRT_OFFSET(treelet) treelet.SubData.z @@ -512,6 +522,9 @@ STriangle SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT); + float aClipMax = MAXFLOAT; + float aClipMin = -MAXFLOAT; + for (bool toContinue = true; toContinue; /* none */) { ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode); @@ -620,7 +633,7 @@ STriangle SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect IntersectTriangle (aSubTree.TrsfRay, aPoints[0], aPoints[1], aPoints[2], aTimeUV, aNormal); - if (aTimeUV.x < theHit.Time) + if (aTimeUV.x > aClipMin && aTimeUV.x < aClipMax && aTimeUV.x < theHit.Time) { aTriangle.TriIndex = aTriIndex; for (int i = 0; i < 3; ++i) @@ -646,12 +659,33 @@ STriangle SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect } else if (aData.x > 0) // switch node { + aClipMax = MAXFLOAT; + aClipMin = -MAXFLOAT; + aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0); vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1); vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2); vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3); + + for (int aPlaneIdx = 0; aInvTransf3.w >= 0.0 && aPlaneIdx < uNbClipPlanes; ++aPlaneIdx) + { + vec4 aSettings = texelFetch (uRaytraceClippingTexture, PLANE_SETTINGS (aInvTransf3, aPlaneIdx)); + vec4 aEquation = texelFetch (uRaytraceClippingTexture, PLANE_EQUATION (aInvTransf3, aPlaneIdx)); + + float aNdotD = -dot (aEquation.xyz, theRay.Direct); + + if (IS_PLANE_ACTIVE (aSettings)) + { + float aPlaneTime = (dot (aEquation.xyz, theRay.Origin) + aEquation.w) / aNdotD; + + if (aNdotD < 0.0) + aClipMin = max (aClipMin, aPlaneTime); + else + aClipMax = min (aClipMax, aPlaneTime); + } + } aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct, aInvTransf0, @@ -689,6 +723,9 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) int aStop = -1; // BVH level switch SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT); + + float aClipMax = MAXFLOAT; + float aClipMin = -MAXFLOAT; for (bool toContinue = true; toContinue; /* none */) { @@ -798,12 +835,12 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) IntersectTriangle (aSubTree.TrsfRay, aPoint0, aPoint1, aPoint2, aTimeUV, aNormal); #ifdef TRANSPARENT_SHADOWS - if (aTimeUV.x < theDistance) + if (aTimeUV.x > aClipMin && aTimeUV.x < aClipMax && aTimeUV.x < theDistance) { aFactor *= 1.f - texelFetch (uRaytraceMaterialTexture, MATERIAL_TRAN (aTriangle.w)).x; } #else - if (aTimeUV.x < theDistance) + if (aTimeUV.x > aClipMin && aTimeUV.x < aClipMax && aTimeUV.x < theDistance) { aFactor = 0.f; } @@ -822,12 +859,33 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) } else if (aData.x > 0) // switch node { + aClipMax = MAXFLOAT; + aClipMin = -MAXFLOAT; + aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0); vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1); vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2); vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3); + + for (int aPlaneIdx = 0; aInvTransf3.w >= 0.0 && aPlaneIdx < uNbClipPlanes; ++aPlaneIdx) + { + vec4 aSettings = texelFetch (uRaytraceClippingTexture, PLANE_SETTINGS (aInvTransf3, aPlaneIdx)); + vec4 aEquation = texelFetch (uRaytraceClippingTexture, PLANE_EQUATION (aInvTransf3, aPlaneIdx)); + + float aNdotD = -dot (aEquation.xyz, theRay.Direct); + + if (IS_PLANE_ACTIVE (aSettings)) + { + float aPlaneTime = (dot (aEquation.xyz, theRay.Origin) + aEquation.w) / aNdotD; + + if (aNdotD < 0.0) + aClipMin = max (aClipMin, aPlaneTime); + else + aClipMax = min (aClipMax, aPlaneTime); + } + } aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct, aInvTransf0, diff --git a/tests/opengl/data/raytrace/clip_planes.tcl b/tests/opengl/data/raytrace/clip_planes.tcl new file mode 100644 index 0000000000..665de40c62 --- /dev/null +++ b/tests/opengl/data/raytrace/clip_planes.tcl @@ -0,0 +1,90 @@ +pload MODELING VISUALIZATION +vclear +vinit name=View1 w=512 h=512 +vglinfo + +# setup light sources +vlight -clear +vlight -add POSITIONAL -headLight 0 -pos 0.5 0.5 0.85 -smoothRadius 0.06 -intensity 30.0 -name pntlight + +vvbo 0 +vsetdispmode 1 +vcamera -persp + +# setup outer box +box b 1 1 1 +explode b FACE +vdisplay -noupdate b_1 b_2 b_3 b_5 b_6 +vlocation -noupdate b_1 -setLocation 1 0 0 +vlocation -noupdate b_2 -setLocation -1 0 0 +vlocation -noupdate b_3 -setLocation 0 1 0 +vlocation -noupdate b_5 -setLocation 0 0 1 +vlocation -noupdate b_6 -setLocation 0 0 -1 + +vsetmaterial -noupdate b_1 plastic +vsetmaterial -noupdate b_2 plastic +vsetmaterial -noupdate b_3 plastic +vsetmaterial -noupdate b_5 plastic +vsetmaterial -noupdate b_6 plastic +vbsdf b_1 -kd 1 0.3 0.3 -ks 0 +vbsdf b_2 -kd 0.3 0.5 1 -ks 0 +vbsdf b_3 -kd 1 -ks 0 +vbsdf b_5 -kd 1 -ks 0 +vbsdf b_6 -kd 1 -ks 0 + +vfront +vfit + +# setup first inner sphere +psphere s 0.2 +vdisplay -noupdate s +vlocation -noupdate s -setLocation 0.21 0.5 0.2 +vsetmaterial -noupdate s glass +vbsdf s -absorpColor 0.8 0.8 1.0 +vbsdf s -absorpCoeff 6 + +# setup first inner box +box c 0.3 0.3 0.2 +vdisplay -noupdate c +vlocation -noupdate c -reset -rotate 0 0 0 0 0 1 -30 -translate 0.55 0.5 0.0 +vsetmaterial -noupdate c plastic +vbsdf c -kd 1.0 0.8 0.2 -ks 0.3 -n + +# setup second inner box +box g 0.25 0.25 0.4 +vdisplay -noupdate g +vlocation -noupdate g -reset -rotate 0 0 0 0 0 1 10 -translate 0.4 0.1 0.0 +vsetmaterial -noupdate g glass +vbsdf g -absorpColor 0.8 1.0 0.8 +vbsdf g -absorpCoeff 6 + +# setup second inner sphere +psphere r 0.1 +vdisplay -noupdate r +vsetmaterial -noupdate r plastic +vbsdf r -kd 0.5 0.9 0.3 -ks 0.3 -baseRoughness 0.0 -n +vbsdf r -baseFresnel Constant 1.0 +vlocation r -setLocation 0.5 0.65 0.1 + +vclipplane create pln +vclipplane change pln equation 0 0 1 -0.1 +vclipplane set pln object s +vclipplane set pln object r +vclipplane set pln object c + +vclipplane create pln2 +vclipplane change pln2 equation 0 0 -1 0.15 +vclipplane set pln2 object s +vclipplane set pln2 object r +vclipplane set pln2 object c + + +puts "Trying path tracing mode..." +vrenderparams -ray -gi -rayDepth 8 + +puts "Make several path tracing iterations to refine the picture, please wait..." +vfps 100 + +vdump $imagedir/${casename}.png +puts "Done. To improve the image further, or after view manipulations, give command:" +puts "vfps \[nb_iteratons\] or vrepaint -continuous"