From: Denis BOGOLEPOV Date: Thu, 3 Mar 2016 10:38:45 +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=1636fd05f67741211f24eeb8e2959c1b27c8b6e9;p=occt-copy.git 0027223: Visualization, Ray Tracing - add support of clipping planes --- diff --git a/samples/tcl/pathtrace.tcl b/samples/tcl/pathtrace.tcl index 713295a370..874c2d04e4 100644 --- a/samples/tcl/pathtrace.tcl +++ b/samples/tcl/pathtrace.tcl @@ -75,4 +75,8 @@ vbsdf r -kd 0.5 0.9 0.3 -ks 0.0 -kr 0.3 -n vbsdf r -fresnel Constant 1.0 vsetlocation r 0.5 0.65 0.1 +vclipplane create pln +vclipplane change pln equation 0 0 -1 0.1 +vclipplane set pln object s + vrenderparams -ray -gi -rayDepth 8 diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx index cc2bee3625..4e7c68c36b 100644 --- a/src/Graphic3d/Graphic3d_CStructure.hxx +++ b/src/Graphic3d/Graphic3d_CStructure.hxx @@ -54,7 +54,7 @@ public: } //! Pass clip planes to the associated graphic driver structure - void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes) { myClipPlanes = thePlanes; } + virtual void SetClipPlanes (const Graphic3d_SequenceOfHClipPlane& thePlanes) { myClipPlanes = thePlanes; } //! @return bounding box of this presentation const Graphic3d_BndBox4f& BoundingBox() const diff --git a/src/OpenGl/OpenGl_SceneGeometry.cxx b/src/OpenGl/OpenGl_SceneGeometry.cxx index cbdb7d035a..1325a7dac8 100755 --- a/src/OpenGl/OpenGl_SceneGeometry.cxx +++ b/src/OpenGl/OpenGl_SceneGeometry.cxx @@ -520,6 +520,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 d64bfbf27a..241d9b8431 100755 --- a/src/OpenGl/OpenGl_SceneGeometry.hxx +++ b/src/OpenGl/OpenGl_SceneGeometry.hxx @@ -223,6 +223,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 (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 { @@ -247,6 +374,10 @@ public: 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 d5e22fc2b9..21c8cb6f6d 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -241,6 +241,20 @@ void OpenGl_Structure::SetAspectText (const CALL_DEF_CONTEXTTEXT &theAspect) myAspectText->SetAspect (theAspect); } +// ======================================================================= +// function : SetClipPlanes +// purpose : +// ======================================================================= +void OpenGl_Structure::SetClipPlanes (const Graphic3d_SequenceOfHClipPlane &thePlanes) +{ + Graphic3d_CStructure::SetClipPlanes (thePlanes); + + if (IsRaytracable()) + { + ++myModificationState; + } +} + // ======================================================================= // function : clearHighlightBox // purpose : diff --git a/src/OpenGl/OpenGl_Structure.hxx b/src/OpenGl/OpenGl_Structure.hxx index 6a4f2157c5..b9d2812dca 100644 --- a/src/OpenGl/OpenGl_Structure.hxx +++ b/src/OpenGl/OpenGl_Structure.hxx @@ -129,6 +129,9 @@ public: Standard_EXPORT void Clear (const Handle(OpenGl_Context)& theGlCtx); + //! Pass clip planes to the associated graphic driver structure + void SetClipPlanes (const 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 026c583469..0f62cd6b29 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -702,12 +702,13 @@ protected: //! @name data types related to ray-tracing OpenGl_RT_RaytraceMaterialTexture = 9, OpenGl_RT_RaytraceLightSrcTexture = 10, + OpenGl_RT_RaytraceClippingTexture = 11, - OpenGl_RT_FsaaInputTexture = 11, - OpenGl_RT_PrevAccumTexture = 12, + OpenGl_RT_FsaaInputTexture = 12, + OpenGl_RT_PrevAccumTexture = 13, - OpenGl_RT_OpenGlColorTexture = 13, - OpenGl_RT_OpenGlDepthTexture = 14 + OpenGl_RT_OpenGlColorTexture = 14, + OpenGl_RT_OpenGlDepthTexture = 15 }; //! Tool class for management of shader sources. @@ -1032,6 +1033,8 @@ protected: //! @name fields related to ray-tracing Handle(OpenGl_TextureBufferArb) myRaytraceMaterialTexture; //! Texture buffer of light source properties. Handle(OpenGl_TextureBufferArb) myRaytraceLightSrcTexture; + //! Texture buffer of clipping planes parameters. + Handle(OpenGl_TextureBufferArb) myRaytraceClippingTexture; //! 1st framebuffer (FBO) to perform adaptive FSAA. Handle(OpenGl_FrameBuffer) myRaytraceFBO1[2]; diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index 0839951abd..46c52ff5e8 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -403,7 +403,7 @@ Standard_Boolean OpenGl_View::addRaytraceStructure (const OpenGl_Structure* return Standard_True; } - // Get structure material + // Get material of the structure OpenGl_RaytraceMaterial aStructMaterial; if (theStructure->AspectFace() != NULL) @@ -435,6 +435,45 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure* const Graphic3d_Mat4* theTransform, const Handle(OpenGl_Context)& theGlContext) { + // ID of clipping plane set + Standard_Integer aClipSetID = -1; + + // Collect clipping planes of structure scope + 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()); + + for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < aUserPlanes->Size(); ++aPlaneIdx) + { + if (aPlaneIdx < OpenGl_RaytraceClipPlanes::MAX_PLANE_NUMBER) + { + myRaytraceGeometry.ClipPlanes.back()[aPlaneIdx].SetEquation (aUserPlanes->operator ()(aPlaneIdx + 1)->GetEquation()); + } + } + + aClipSetID = static_cast (myRaytraceGeometry.ClipPlanes.size() - 1); + } + } + for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->DrawGroups()); aGroupIter.More(); aGroupIter.Next()) { // Get group material @@ -476,13 +515,18 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure* { OpenGl_TriangleSet* aSet = aSetIter->second; - BVH_Transform* aTransform = new BVH_Transform(); + OpenGl_RaytraceTransform* aTransform = new OpenGl_RaytraceTransform; if (theTransform != NULL) { aTransform->SetTransform (*theTransform); } + if (aClipSetID != OpenGl_RaytraceTransform::NO_CLIPPING) + { + aTransform->SetClipSetID (aClipSetID); + } + aSet->SetProperties (aTransform); if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID) @@ -492,18 +536,22 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure* } else { - NCollection_Handle > aSet = - addRaytracePrimitiveArray (aPrimArray, aMatID, 0); + NCollection_Handle > aSet = addRaytracePrimitiveArray (aPrimArray, aMatID, 0); if (!aSet.IsNull()) { - BVH_Transform* aTransform = new BVH_Transform; + OpenGl_RaytraceTransform* aTransform = new OpenGl_RaytraceTransform; if (theTransform != NULL) { aTransform->SetTransform (*theTransform); } + if (aClipSetID != OpenGl_RaytraceTransform::NO_CLIPPING) + { + aTransform->SetClipSetID (aClipSetID); + } + aSet->SetProperties (aTransform); myRaytraceGeometry.Objects().Append (aSet); @@ -1478,6 +1526,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture); aShaderProgram->SetSampler (theGlContext, "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture); + aShaderProgram->SetSampler (theGlContext, + "uRaytraceClippingTexture", OpenGl_RT_RaytraceClippingTexture); aShaderProgram->SetSampler (theGlContext, "uOpenGlColorTexture", OpenGl_RT_OpenGlColorTexture); @@ -1629,6 +1679,7 @@ void OpenGl_View::releaseRaytraceResources (const Handle(OpenGl_Context)& theGlC nullifyResource (theGlContext, myRaytraceLightSrcTexture); nullifyResource (theGlContext, myRaytraceMaterialTexture); + nullifyResource (theGlContext, myRaytraceClippingTexture); myRaytraceGeometry.ReleaseResources (theGlContext); @@ -1760,7 +1811,7 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)& } ///////////////////////////////////////////////////////////////////////////// - // Create OpenGL BVH buffers + // Create BVH buffers if (mySceneNodeInfoTexture.IsNull()) // create scene BVH buffers { @@ -1800,6 +1851,9 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)& } } + ///////////////////////////////////////////////////////////////////////////// + // Create material buffer + if (myRaytraceMaterialTexture.IsNull()) // create material buffer { myRaytraceMaterialTexture = new OpenGl_TextureBufferArb; @@ -1807,7 +1861,23 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)& if (!myRaytraceMaterialTexture->Create (theGlContext)) { #ifdef RAY_TRACE_PRINT_INFO - std::cout << "Error: Failed to create buffers for material data" << std::endl; + std::cout << "Error: Failed to create buffer for material data" << std::endl; +#endif + return Standard_False; + } + } + + ///////////////////////////////////////////////////////////////////////////// + // Create clip planes buffer + + if (myRaytraceClippingTexture.IsNull()) // create clipping planes buffer + { + myRaytraceClippingTexture = new OpenGl_TextureBufferArb; + + 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; } @@ -1825,13 +1895,17 @@ 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().operator->()); + 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, @@ -2006,6 +2080,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 @@ -2294,6 +2385,7 @@ void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlConte mySceneTransformTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture); myRaytraceMaterialTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture); myRaytraceLightSrcTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture); + myRaytraceClippingTexture->BindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceClippingTexture); if (!myOpenGlFBO.IsNull()) { @@ -2318,6 +2410,7 @@ void OpenGl_View::unbindRaytraceTextures (const Handle(OpenGl_Context)& theGlCon mySceneTransformTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture); myRaytraceMaterialTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture); myRaytraceLightSrcTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture); + myRaytraceClippingTexture->UnbindTexture (theGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceClippingTexture); if (!myOpenGlFBO.IsNull()) { diff --git a/src/Shaders/RaytraceBase.fs b/src/Shaders/RaytraceBase.fs index 13f17b26d4..5676879fc7 100644 --- a/src/Shaders/RaytraceBase.fs +++ b/src/Shaders/RaytraceBase.fs @@ -60,6 +60,9 @@ uniform isamplerBuffer uGeometryTriangTexture; uniform samplerBuffer uRaytraceMaterialTexture; //! Texture buffer of light source properties. uniform samplerBuffer uRaytraceLightSrcTexture; +//! Texture buffer of clipping planes properties. +uniform samplerBuffer uRaytraceClippingTexture; + //! Environment map texture. uniform sampler2D uEnvironmentMapTexture; @@ -375,12 +378,20 @@ struct SSubTree ivec4 SubData; }; +#define EMPTY_ROOT ivec4(0) + #define TRS_OFFSET(treelet) treelet.SubData.x #define BVH_OFFSET(treelet) treelet.SubData.y #define VRT_OFFSET(treelet) treelet.SubData.z #define TRG_OFFSET(treelet) treelet.SubData.w -#define EMPTY_ROOT ivec4(0) +#define MAX_CLIP_PLANES 1 + +#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) // ======================================================================= // function : SceneNearestHit @@ -396,6 +407,9 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT); + float aClipMax = MAXFLOAT; + float aClipMin = -MAXFLOAT; + for (bool toContinue = true; toContinue;) { ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode); @@ -472,7 +486,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH float aTime = IntersectTriangle (aSubTree.TrsfRay, aPoint0, aPoint1, aPoint2, aParams, aNormal); - if (aTime < theHit.Time) + if (aTime > aClipMin && aTime < aClipMax && aTime < theHit.Time) { aTriIndex = aTriangle; @@ -493,13 +507,34 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH } else if (aData.x > 0) // switch node { - aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root + aClipMax = MAXFLOAT; + aClipMin = -MAXFLOAT; + + aSubTree.SubData = ivec4 (aData.x * 4 - 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 < MAX_CLIP_PLANES; ++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, aInvTransf1, @@ -537,6 +572,9 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT); + float aClipMax = MAXFLOAT; + float aClipMin = -MAXFLOAT; + for (bool toContinue = true; toContinue;) { ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode); @@ -614,12 +652,12 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) aPoint0, aPoint1, aPoint2, aParams, aNormal); #ifdef TRANSPARENT_SHADOWS - if (aTime < theDistance) + if (aTime > aClipMin && aTime < aClipMax && aTime < theDistance) { aFactor *= 1.f - texelFetch (uRaytraceMaterialTexture, MATERIAL_TRAN (aTriangle.w)).x; } #else - if (aTime < theDistance) + if (aTime > aClipMin && aTime < aClipMax && aTime < theDistance) { aFactor = 0.f; } @@ -637,6 +675,9 @@ 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); @@ -644,6 +685,24 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance) 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 < MAX_CLIP_PLANES; ++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, aInvTransf1,