diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index a7820bf1a8..b97d4d5722 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -87,6 +87,7 @@ Graphic3d_Camera::Graphic3d_Camera() myZNear (DEFAULT_ZNEAR), myZFar (DEFAULT_ZFAR), myAspect (1.0), + myIsZeroToOneDepth (false), myScale (1000.0), myZFocus (1.0), myZFocusType (FocusType_Relative), @@ -119,6 +120,7 @@ Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther) myZNear (DEFAULT_ZNEAR), myZFar (DEFAULT_ZFAR), myAspect (1.0), + myIsZeroToOneDepth (false), myScale (1000.0), myZFocus (1.0), myZFocusType (FocusType_Relative), @@ -139,6 +141,7 @@ Graphic3d_Camera::Graphic3d_Camera (const Handle(Graphic3d_Camera)& theOther) // ======================================================================= void Graphic3d_Camera::CopyMappingData (const Handle(Graphic3d_Camera)& theOtherCamera) { + SetZeroToOneDepth (theOtherCamera->IsZeroToOneDepth()); SetProjectionType (theOtherCamera->ProjectionType()); SetFOVy (theOtherCamera->FOVy()); SetFOV2d (theOtherCamera->FOV2d()); @@ -1247,7 +1250,7 @@ template void Graphic3d_Camera::orthoProj (NCollection_Mat4& theOutMx, const Aspect_FrustumLRBT& theLRBT, const Elem_t theNear, - const Elem_t theFar) + const Elem_t theFar) const { // row 0 theOutMx.ChangeValue (0, 0) = Elem_t (2.0) / (theLRBT.Right - theLRBT.Left); @@ -1264,8 +1267,16 @@ void Graphic3d_Camera::orthoProj (NCollection_Mat4& theOutMx, // row 2 theOutMx.ChangeValue (2, 0) = Elem_t (0.0); theOutMx.ChangeValue (2, 1) = Elem_t (0.0); - theOutMx.ChangeValue (2, 2) = Elem_t (-2.0) / (theFar - theNear); - theOutMx.ChangeValue (2, 3) = - (theFar + theNear) / (theFar - theNear); + if (myIsZeroToOneDepth) + { + theOutMx.ChangeValue (2, 2) = Elem_t (-1.0) / (theFar - theNear); + theOutMx.ChangeValue (2, 3) = -theNear / (theFar - theNear); + } + else + { + theOutMx.ChangeValue (2, 2) = Elem_t (-2.0) / (theFar - theNear); + theOutMx.ChangeValue (2, 3) = - (theFar + theNear) / (theFar - theNear); + } // row 3 theOutMx.ChangeValue (3, 0) = Elem_t (0.0); @@ -1282,7 +1293,7 @@ template void Graphic3d_Camera::perspectiveProj (NCollection_Mat4& theOutMx, const Aspect_FrustumLRBT& theLRBT, const Elem_t theNear, - const Elem_t theFar) + const Elem_t theFar) const { // column 0 theOutMx.ChangeValue (0, 0) = (Elem_t (2.0) * theNear) / (theLRBT.Right - theLRBT.Left); @@ -1299,13 +1310,27 @@ void Graphic3d_Camera::perspectiveProj (NCollection_Mat4& theOutMx, // column 2 theOutMx.ChangeValue (0, 2) = (theLRBT.Right + theLRBT.Left) / (theLRBT.Right - theLRBT.Left); theOutMx.ChangeValue (1, 2) = (theLRBT.Top + theLRBT.Bottom) / (theLRBT.Top - theLRBT.Bottom); - theOutMx.ChangeValue (2, 2) = -(theFar + theNear) / (theFar - theNear); + if (myIsZeroToOneDepth) + { + theOutMx.ChangeValue (2, 2) = theFar / (theNear - theFar); + } + else + { + theOutMx.ChangeValue (2, 2) = -(theFar + theNear) / (theFar - theNear); + } theOutMx.ChangeValue (3, 2) = Elem_t (-1.0); // column 3 theOutMx.ChangeValue (0, 3) = Elem_t (0.0); theOutMx.ChangeValue (1, 3) = Elem_t (0.0); - theOutMx.ChangeValue (2, 3) = -(Elem_t (2.0) * theFar * theNear) / (theFar - theNear); + if (myIsZeroToOneDepth) + { + theOutMx.ChangeValue (2, 3) = -(theFar * theNear) / (theFar - theNear); + } + else + { + theOutMx.ChangeValue (2, 3) = -(Elem_t (2.0) * theFar * theNear) / (theFar - theNear); + } theOutMx.ChangeValue (3, 3) = Elem_t (0.0); } @@ -1320,7 +1345,7 @@ void Graphic3d_Camera::stereoEyeProj (NCollection_Mat4& theOutMx, const Elem_t theFar, const Elem_t theIOD, const Elem_t theZFocus, - const Aspect_Eye theEyeIndex) + const Aspect_Eye theEyeIndex) const { Elem_t aDx = theEyeIndex == Aspect_Eye_Left ? Elem_t (0.5) * theIOD : Elem_t (-0.5) * theIOD; Elem_t aDXStereoShift = aDx * theNear / theZFocus; @@ -1829,12 +1854,10 @@ void Graphic3d_Camera::FrustumPoints (NCollection_Array1& thePo Standard_Real nLeft = 0.0, nRight = 0.0, nTop = 0.0, nBottom = 0.0; Standard_Real fLeft = 0.0, fRight = 0.0, fTop = 0.0, fBottom = 0.0; - Standard_Real aNear = 0.0, aFar = 0.0; + Standard_Real aNear = myZNear, aFar = myZFar; if (!IsOrthographic()) { // handle perspective projection - aNear = aProjectionMat.GetValue (2, 3) / (-1.0 + aProjectionMat.GetValue (2, 2)); - aFar = aProjectionMat.GetValue (2, 3) / ( 1.0 + aProjectionMat.GetValue (2, 2)); // Near plane nLeft = aNear * (aProjectionMat.GetValue (0, 2) - 1.0) / aProjectionMat.GetValue (0, 0); nRight = aNear * (aProjectionMat.GetValue (0, 2) + 1.0) / aProjectionMat.GetValue (0, 0); @@ -1849,8 +1872,6 @@ void Graphic3d_Camera::FrustumPoints (NCollection_Array1& thePo else { // handle orthographic projection - aNear = (1.0 / aProjectionMat.GetValue (2, 2)) * (aProjectionMat.GetValue (2, 3) + 1.0); - aFar = (1.0 / aProjectionMat.GetValue (2, 2)) * (aProjectionMat.GetValue (2, 3) - 1.0); // Near plane nLeft = ( 1.0 + aProjectionMat.GetValue (0, 3)) / (-aProjectionMat.GetValue (0, 0)); fLeft = nLeft; diff --git a/src/Graphic3d/Graphic3d_Camera.hxx b/src/Graphic3d/Graphic3d_Camera.hxx index 966bd57c92..8197b42e13 100644 --- a/src/Graphic3d/Graphic3d_Camera.hxx +++ b/src/Graphic3d/Graphic3d_Camera.hxx @@ -413,6 +413,20 @@ public: return myZFar; } + //! Return TRUE if camera should calculate projection matrix for [0, 1] depth range or for [-1, 1] range. + //! FALSE by default. + Standard_Boolean IsZeroToOneDepth() const { return myIsZeroToOneDepth; } + + //! Set using [0, 1] depth range or [-1, 1] range. + void SetZeroToOneDepth (Standard_Boolean theIsZeroToOne) + { + if (myIsZeroToOneDepth != theIsZeroToOne) + { + myIsZeroToOneDepth = theIsZeroToOne; + InvalidateProjection(); + } + } + //! Changes width / height display ratio. //! @param theAspect [in] the display ratio. Standard_EXPORT void SetAspect (const Standard_Real theAspect); @@ -747,10 +761,10 @@ private: //! @param theNear [in] the near mapping (clipping) coordinate //! @param theFar [in] the far mapping (clipping) coordinate template - static void orthoProj (NCollection_Mat4& theOutMx, - const Aspect_FrustumLRBT& theLRBT, - const Elem_t theNear, - const Elem_t theFar); + void orthoProj (NCollection_Mat4& theOutMx, + const Aspect_FrustumLRBT& theLRBT, + const Elem_t theNear, + const Elem_t theFar) const; //! Compose perspective projection matrix for the passed camera volume mapping. //! @param theOutMx [out] the projection matrix @@ -758,10 +772,10 @@ private: //! @param theNear [in] the near mapping (clipping) coordinate //! @param theFar [in] the far mapping (clipping) coordinate template - static void perspectiveProj (NCollection_Mat4& theOutMx, - const Aspect_FrustumLRBT& theLRBT, - const Elem_t theNear, - const Elem_t theFar); + void perspectiveProj (NCollection_Mat4& theOutMx, + const Aspect_FrustumLRBT& theLRBT, + const Elem_t theNear, + const Elem_t theFar) const; //! Compose projection matrix for L/R stereo eyes. //! @param theOutMx [out] the projection matrix @@ -772,13 +786,13 @@ private: //! @param theZFocus [in] the z coordinate of off-axis projection plane with zero parallax //! @param theEyeIndex [in] choose between L/R eyes template - static void stereoEyeProj (NCollection_Mat4& theOutMx, - const Aspect_FrustumLRBT& theLRBT, - const Elem_t theNear, - const Elem_t theFar, - const Elem_t theIOD, - const Elem_t theZFocus, - const Aspect_Eye theEyeIndex); + void stereoEyeProj (NCollection_Mat4& theOutMx, + const Aspect_FrustumLRBT& theLRBT, + const Elem_t theNear, + const Elem_t theFar, + const Elem_t theIOD, + const Elem_t theZFocus, + const Aspect_Eye theEyeIndex) const; //! Construct "look at" orientation transformation. //! Reference point differs for perspective and ortho modes @@ -835,6 +849,7 @@ private: Standard_Real myZNear; //!< Distance to near clipping plane. Standard_Real myZFar; //!< Distance to far clipping plane. Standard_Real myAspect; //!< Width to height display ratio. + Standard_Boolean myIsZeroToOneDepth; //!< use [0, 1] depth range or [-1, 1] Standard_Real myScale; //!< Specifies parallel scale for orthographic projection. Standard_Real myZFocus; //!< Stereographic focus value. diff --git a/src/OpenGl/OpenGl_Caps.cxx b/src/OpenGl/OpenGl_Caps.cxx index 03ecc8b2ed..b339c15d15 100755 --- a/src/OpenGl/OpenGl_Caps.cxx +++ b/src/OpenGl/OpenGl_Caps.cxx @@ -37,6 +37,7 @@ OpenGl_Caps::OpenGl_Caps() useSystemBuffer (Standard_True), #endif swapInterval (1), + useZeroToOneDepth (Standard_False), buffersNoSwap (Standard_False), buffersOpaqueAlpha(Standard_False), contextStereo (Standard_False), @@ -78,6 +79,7 @@ OpenGl_Caps& OpenGl_Caps::operator= (const OpenGl_Caps& theCopy) ffpEnable = theCopy.ffpEnable; useSystemBuffer = theCopy.useSystemBuffer; swapInterval = theCopy.swapInterval; + useZeroToOneDepth = theCopy.useZeroToOneDepth; buffersNoSwap = theCopy.buffersNoSwap; buffersOpaqueAlpha= theCopy.buffersOpaqueAlpha; contextStereo = theCopy.contextStereo; diff --git a/src/OpenGl/OpenGl_Caps.hxx b/src/OpenGl/OpenGl_Caps.hxx index 6657515cf9..d940260811 100755 --- a/src/OpenGl/OpenGl_Caps.hxx +++ b/src/OpenGl/OpenGl_Caps.hxx @@ -36,6 +36,7 @@ public: //! @name flags to disable particular functionality, should be used only Standard_Boolean usePolygonMode; //!< Enables Polygon Mode instead of built-in GLSL programs (OFF by default; unsupported on OpenGL ES) Standard_Boolean useSystemBuffer; //!< Enables usage of system backbuffer for blitting (OFF by default on desktop OpenGL and ON on OpenGL ES for testing) Standard_Integer swapInterval; //!< controls swap interval - 0 for VSync off and 1 for VSync on, 1 by default + Standard_Boolean useZeroToOneDepth; //!< use [0, 1] depth range instead of [-1, 1] range, when possible (OFF by default) public: //! @name context creation parameters diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 39d3edcd13..1fcd4c847e 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -184,6 +184,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) arbTexBindless (NULL), arbTBO (NULL), arbTboRGB32 (Standard_False), + arbClipControl (Standard_False), arbIns (NULL), arbDbg (NULL), arbFBO (NULL), diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 55b766baba..e72ea2e9c4 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -1110,6 +1110,7 @@ public: //! @name extensions OpenGl_ArbTexBindless* arbTexBindless; //!< GL_ARB_bindless_texture OpenGl_ArbTBO* arbTBO; //!< GL_ARB_texture_buffer_object (on desktop OpenGL - since 3.1 or as extension GL_ARB_texture_buffer_object; on OpenGL ES - since 3.2) Standard_Boolean arbTboRGB32; //!< GL_ARB_texture_buffer_object_rgb32 (3-component TBO), in core since 4.0 (on OpenGL ES - since 3.2) + Standard_Boolean arbClipControl; //!< GL_ARB_clip_control, in core since 4.5 OpenGl_ArbIns* arbIns; //!< GL_ARB_draw_instanced (on desktop OpenGL - since 3.1 or as extension GL_ARB_draw_instanced; on OpenGL ES - since 3.0 or as extension GL_ANGLE_instanced_arrays to WebGL 1.0) OpenGl_ArbDbg* arbDbg; //!< GL_ARB_debug_output (on desktop OpenGL - since 4.3 or as extension GL_ARB_debug_output; on OpenGL ES - since 3.2 or as extension GL_KHR_debug) OpenGl_ArbFBO* arbFBO; //!< GL_ARB_framebuffer_object diff --git a/src/OpenGl/OpenGl_GlFunctions.cxx b/src/OpenGl/OpenGl_GlFunctions.cxx index 3f3fd239f7..63afab47f9 100644 --- a/src/OpenGl/OpenGl_GlFunctions.cxx +++ b/src/OpenGl/OpenGl_GlFunctions.cxx @@ -65,6 +65,7 @@ void OpenGl_GlFunctions::load (OpenGl_Context& theCtx, theCtx.core46back = NULL; theCtx.arbTBO = NULL; theCtx.arbTboRGB32 = false; + theCtx.arbClipControl = false; theCtx.arbIns = NULL; theCtx.arbDbg = NULL; theCtx.arbFBO = NULL; @@ -1636,6 +1637,7 @@ void OpenGl_GlFunctions::load (OpenGl_Context& theCtx, if (has45) { theCtx.core45 = (OpenGl_GlCore45* )this; + theCtx.arbClipControl = true; if (!isCoreProfile) { theCtx.core45back = (OpenGl_GlCore45Back* )this; @@ -1718,6 +1720,13 @@ void OpenGl_GlFunctions::load (OpenGl_Context& theCtx, theCtx.arbTexBindless = (OpenGl_ArbTexBindless* )this; } + if (!has45 + && checkExtensionShort ("GL_ARB_clip_control") + && FindProcShort (glClipControl)) + { + theCtx.arbClipControl = true; + } + if (has30) { if (!has32 diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 040724fb45..252e024f95 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -436,6 +436,11 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& { aHeaderConstants += TCollection_AsciiString("#define THE_NB_SHADOWMAPS ") + myNbShadowMaps + "\n"; } + if (theCtx->caps->useZeroToOneDepth + && theCtx->arbClipControl) + { + aHeaderConstants += "#define THE_ZERO_TO_ONE_DEPTH\n"; + } if (!myProxy.IsNull() && myProxy->HasDefaultSampler()) { diff --git a/src/OpenGl/OpenGl_ShadowMap.cxx b/src/OpenGl/OpenGl_ShadowMap.cxx index c1db3db21a..749e9c8a36 100644 --- a/src/OpenGl/OpenGl_ShadowMap.cxx +++ b/src/OpenGl/OpenGl_ShadowMap.cxx @@ -115,6 +115,7 @@ bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView, theView.Camera()->OrientationMatrix().Inverted (anOrientInv); aDir = anOrientInv * aDir; } + myShadowCamera->SetZeroToOneDepth (theView.Camera()->IsZeroToOneDepth()); myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic); myShadowCamera->SetDirection (gp_Dir (aDir.x(), aDir.y(), aDir.z())); myShadowCamera->SetUp (!myShadowCamera->Direction().IsParallel (gp::DY(), Precision::Angular()) diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 8ccda34be8..5a8d6f0270 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -745,6 +745,9 @@ protected: //! @name data types related to ray-tracing //! Actual ray-tracing depth (number of ray bounces). Standard_Integer NbBounces; + //! Define depth computation + Standard_Boolean IsZeroToOneDepth; + //! Enables/disables light propagation through transparent media. Standard_Boolean TransparentShadows; @@ -785,6 +788,7 @@ protected: //! @name data types related to ray-tracing RaytracingParams() : StackSize (THE_DEFAULT_STACK_SIZE), NbBounces (THE_DEFAULT_NB_BOUNCES), + IsZeroToOneDepth (Standard_False), TransparentShadows (Standard_False), GlobalIllumination (Standard_False), UseBindlessTextures (Standard_False), diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index 9c6662ac43..c3cb44a7ce 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -1139,6 +1139,11 @@ TCollection_AsciiString OpenGl_View::generateShaderPrefix (const Handle(OpenGl_C TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" + TCollection_AsciiString ("#define NB_BOUNCES ") + TCollection_AsciiString (myRaytraceParameters.NbBounces); + if (myRaytraceParameters.IsZeroToOneDepth) + { + aPrefixString += TCollection_AsciiString ("\n#define THE_ZERO_TO_ONE_DEPTH"); + } + if (myRaytraceParameters.TransparentShadows) { aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS"); @@ -1364,13 +1369,17 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS } } - if (myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces + const bool isZeroToOneDepth = myCaps->useZeroToOneDepth + && myWorkspace->GetGlContext()->arbClipControl; + if (isZeroToOneDepth != myRaytraceParameters.IsZeroToOneDepth + || myRenderParams.RaytracingDepth != myRaytraceParameters.NbBounces || myRenderParams.IsTransparentShadowEnabled != myRaytraceParameters.TransparentShadows || myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination || myRenderParams.TwoSidedBsdfModels != myRaytraceParameters.TwoSidedBsdfModels || myRaytraceGeometry.HasTextures() != myRaytraceParameters.UseBindlessTextures || myRenderParams.ToIgnoreNormalMapInRayTracing != myRaytraceParameters.ToIgnoreNormalMap) { + myRaytraceParameters.IsZeroToOneDepth = isZeroToOneDepth; myRaytraceParameters.NbBounces = myRenderParams.RaytracingDepth; myRaytraceParameters.TransparentShadows = myRenderParams.IsTransparentShadowEnabled; myRaytraceParameters.GlobalIllumination = myRenderParams.IsGlobalIlluminationEnabled; diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index 04cb70d461..fc595a42dc 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -180,6 +180,20 @@ Standard_Boolean OpenGl_Workspace::Activate() } } + if (myGlContext->caps->useZeroToOneDepth + && !myGlContext->arbClipControl) + { + Message::SendWarning ("Warning: glClipControl() requires OpenGL 4.5 or GL_ARB_clip_control extension"); + myGlContext->caps->useZeroToOneDepth = false; + } + myView->Camera()->SetZeroToOneDepth (myGlContext->caps->useZeroToOneDepth); +#if !defined(GL_ES_VERSION_2_0) + if (myGlContext->arbClipControl) + { + myGlContext->Functions()->glClipControl (GL_LOWER_LEFT, myGlContext->caps->useZeroToOneDepth ? GL_ZERO_TO_ONE : GL_NEGATIVE_ONE_TO_ONE); + } +#endif + ResetAppliedAspect(); // reset state for safety diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index ffc984f77a..a373ad0224 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -41,7 +41,7 @@ void SelectMgr_BaseFrustum::SetCamera (const Handle(Graphic3d_Camera)& theCamera { myCamera = theCamera; myBuilder->SetWorldViewMatrix (theCamera->OrientationMatrix()); - myBuilder->SetProjectionMatrix (theCamera->ProjectionMatrix()); + myBuilder->SetProjectionMatrix (theCamera->ProjectionMatrix(), theCamera->IsZeroToOneDepth()); myBuilder->SetWorldViewProjState (theCamera->WorldViewProjState()); myIsOrthographic = theCamera->IsOrthographic(); myBuilder->InvalidateViewport(); @@ -58,7 +58,7 @@ void SelectMgr_BaseFrustum::SetCamera (const Graphic3d_Mat4d& theProjection, { myCamera.Nullify(); myBuilder->SetWorldViewMatrix (theWorldView); - myBuilder->SetProjectionMatrix (theProjection); + myBuilder->SetProjectionMatrix (theProjection, false); myBuilder->SetWorldViewProjState (theWVPState); myIsOrthographic = theIsOrthographic; } diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx index c5c83486db..3cb0b31957 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx @@ -31,7 +31,8 @@ SelectMgr_FrustumBuilder::SelectMgr_FrustumBuilder() myWorldViewProjState(), myWidth (INT_MAX), myHeight (INT_MAX), - myIsViewportSet (Standard_False) + myIsViewportSet (Standard_False), + myIsZeroToOneDepth (Standard_False) { // } @@ -58,9 +59,11 @@ const Graphic3d_Mat4d& SelectMgr_FrustumBuilder::WorldViewMatrix() const // function : SetProjectionMatrix // purpose : Stores current projection matrix //======================================================================= -void SelectMgr_FrustumBuilder::SetProjectionMatrix (const Graphic3d_Mat4d& theProjection) +void SelectMgr_FrustumBuilder::SetProjectionMatrix (const Graphic3d_Mat4d& theProjection, + const Standard_Boolean theIsZeroToOneDepth) { myProjection = theProjection; + myIsZeroToOneDepth = theIsZeroToOneDepth; } //======================================================================= @@ -180,23 +183,19 @@ static NCollection_Vec4 safePointCast (const gp_Pnt& thePnt) //======================================================================= gp_Pnt SelectMgr_FrustumBuilder::unProject (const gp_Pnt& thePnt) const { - Graphic3d_Mat4d aInvView; - Graphic3d_Mat4d aInvProj; - - // this case should never happen + // inversed matrices could be cached + Graphic3d_Mat4d aInvView, aInvProj; if (!myWorldView.Inverted (aInvView) || !myProjection.Inverted (aInvProj)) { - return gp_Pnt (0.0, 0.0, 0.0); + return gp_Pnt (0.0, 0.0, 0.0); // this case should never happen } // use compatible type of point NCollection_Vec4 aPnt = safePointCast (thePnt); - aPnt = aInvProj * aPnt; // convert to view coordinate space aPnt = aInvView * aPnt; // convert to world coordinate space const Standard_Real aInvW = 1.0 / Standard_Real (aPnt.w()); - return gp_Pnt (aPnt.x() * aInvW, aPnt.y() * aInvW, aPnt.z() * aInvW); } @@ -210,23 +209,19 @@ gp_Pnt SelectMgr_FrustumBuilder::ProjectPntOnViewPlane (const Standard_Real& the const Standard_Real& theY, const Standard_Real& theZ) const { - Standard_Real aX, anY, aZ; - // map coords to NDC + gp_Pnt anXYZ; if (!myIsViewportSet) { - aX = 2.0 * theX / myWidth - 1.0; - anY = (myHeight - 1 - theY) / myHeight * 2.0 - 1.0; - aZ = 2.0 * theZ - 1.0; + anXYZ.SetCoord (2.0 * theX / myWidth - 1.0, + (myHeight - 1 - theY) / myHeight * 2.0 - 1.0, + myIsZeroToOneDepth ? theZ : (2.0 * theZ - 1.0)); } else { - aX = 2.0 * (theX - myWidth * myViewport.x()) / - (myWidth * (myViewport.z() - myViewport.x())) - 1.0; - anY = 2.0 * (theY - myHeight * myViewport.y()) / - (myHeight * (myViewport.w() - myViewport.y())) - 1.0; - aZ = theZ; + anXYZ.SetCoord (2.0 * (theX - myWidth * myViewport.x()) / (myWidth * (myViewport.z() - myViewport.x())) - 1.0, + 2.0 * (theY - myHeight * myViewport.y()) / (myHeight * (myViewport.w() - myViewport.y())) - 1.0, + theZ); } - - return unProject (gp_Pnt (aX, anY, aZ)); + return unProject (anXYZ); } diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx index 7dc0d649ca..e6f84ca51b 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx @@ -39,7 +39,8 @@ public: Standard_EXPORT const Graphic3d_Mat4d& WorldViewMatrix() const; //! Stores current projection matrix - Standard_EXPORT void SetProjectionMatrix (const Graphic3d_Mat4d& theProjection); + Standard_EXPORT void SetProjectionMatrix (const Graphic3d_Mat4d& theProjection, + const Standard_Boolean theIsZeroToOneDepth); //! @return current projection matrix Standard_EXPORT const Graphic3d_Mat4d& ProjectionMatrix() const; @@ -93,6 +94,7 @@ private: Standard_Integer myHeight; NCollection_Vec4 myViewport; Standard_Boolean myIsViewportSet; + Standard_Boolean myIsZeroToOneDepth; }; DEFINE_STANDARD_HANDLE(SelectMgr_FrustumBuilder, Standard_Transient) diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 6f6171d03d..30805b3e38 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -652,7 +652,8 @@ void SelectMgr_ViewerSelector::TraverseSensitives() // define corresponding frustum builder parameters Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder(); - aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix()); + aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix(), + !aCamera.IsNull() && aCamera->IsZeroToOneDepth()); aBuilder->SetWorldViewMatrix (SelectMgr_ViewerSelector_THE_IDENTITY_MAT); aBuilder->SetWindowSize (aWidth, aHeight); aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder); diff --git a/src/Shaders/DirectionalLightShadow.glsl b/src/Shaders/DirectionalLightShadow.glsl index 25a90a0c26..dd980713f5 100644 --- a/src/Shaders/DirectionalLightShadow.glsl +++ b/src/Shaders/DirectionalLightShadow.glsl @@ -16,7 +16,12 @@ float occDirectionalLightShadow (in sampler2D theShadow, { vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)]; vec3 aLightDir = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0)); - vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w) * 0.5 + vec3 (0.5); + vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w); +#ifdef THE_ZERO_TO_ONE_DEPTH + aProjCoords.xy = aProjCoords.xy * 0.5 + vec2 (0.5); +#else + aProjCoords = aProjCoords * 0.5 + vec3 (0.5); +#endif float aCurrentDepth = aProjCoords.z; if (aProjCoords.x < 0.0 || aProjCoords.x > 1.0 || aProjCoords.y < 0.0 || aProjCoords.y > 1.0 diff --git a/src/Shaders/PathtraceBase.fs b/src/Shaders/PathtraceBase.fs index 46a687012c..caea6c193e 100644 --- a/src/Shaders/PathtraceBase.fs +++ b/src/Shaders/PathtraceBase.fs @@ -820,7 +820,11 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples) vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f); float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin); + #ifdef THE_ZERO_TO_ONE_DEPTH + aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE); + #else aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f; + #endif } SBSDF aBSDF; diff --git a/src/Shaders/RaytraceBase.fs b/src/Shaders/RaytraceBase.fs index 176cbe66e6..e31b56e6bb 100644 --- a/src/Shaders/RaytraceBase.fs +++ b/src/Shaders/RaytraceBase.fs @@ -1082,7 +1082,11 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse) vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f); float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin); + #ifdef THE_ZERO_TO_ONE_DEPTH + aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE); + #else aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f; + #endif } vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex); diff --git a/src/Shaders/Shaders_DirectionalLightShadow_glsl.pxx b/src/Shaders/Shaders_DirectionalLightShadow_glsl.pxx index aed61e598c..5b93571baf 100644 --- a/src/Shaders/Shaders_DirectionalLightShadow_glsl.pxx +++ b/src/Shaders/Shaders_DirectionalLightShadow_glsl.pxx @@ -19,7 +19,12 @@ static const char Shaders_DirectionalLightShadow_glsl[] = "{\n" " vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)];\n" " vec3 aLightDir = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0));\n" - " vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w) * 0.5 + vec3 (0.5);\n" + " vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w);\n" + "#ifdef THE_ZERO_TO_ONE_DEPTH\n" + " aProjCoords.xy = aProjCoords.xy * 0.5 + vec2 (0.5);\n" + "#else\n" + " aProjCoords = aProjCoords * 0.5 + vec3 (0.5);\n" + "#endif\n" " float aCurrentDepth = aProjCoords.z;\n" " if (aProjCoords.x < 0.0 || aProjCoords.x > 1.0\n" " || aProjCoords.y < 0.0 || aProjCoords.y > 1.0\n" diff --git a/src/Shaders/Shaders_PathtraceBase_fs.pxx b/src/Shaders/Shaders_PathtraceBase_fs.pxx index ab7c0dddcc..6da9ccde8b 100644 --- a/src/Shaders/Shaders_PathtraceBase_fs.pxx +++ b/src/Shaders/Shaders_PathtraceBase_fs.pxx @@ -823,7 +823,11 @@ static const char Shaders_PathtraceBase_fs[] = " vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);\n" "\n" " float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin);\n" + " #ifdef THE_ZERO_TO_ONE_DEPTH\n" + " aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE);\n" + " #else\n" " aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f;\n" + " #endif\n" " }\n" "\n" " SBSDF aBSDF;\n" diff --git a/src/Shaders/Shaders_RaytraceBase_fs.pxx b/src/Shaders/Shaders_RaytraceBase_fs.pxx index c7f6a4a468..3b54d4ed4f 100644 --- a/src/Shaders/Shaders_RaytraceBase_fs.pxx +++ b/src/Shaders/Shaders_RaytraceBase_fs.pxx @@ -1085,7 +1085,11 @@ static const char Shaders_RaytraceBase_fs[] = " vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);\n" "\n" " float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin);\n" + " #ifdef THE_ZERO_TO_ONE_DEPTH\n" + " aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE);\n" + " #else\n" " aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f;\n" + " #endif\n" " }\n" "\n" " vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);\n" diff --git a/src/V3d/V3d_View.cxx b/src/V3d/V3d_View.cxx index a5a5c3fe9b..08b4a03584 100644 --- a/src/V3d/V3d_View.cxx +++ b/src/V3d/V3d_View.cxx @@ -1701,25 +1701,23 @@ void V3d_View::Convert(const Standard_Real Xv, //function : Convert //purpose : //======================================================================= -void V3d_View::Convert(const Standard_Integer Xp, - const Standard_Integer Yp, - Standard_Real& X, - Standard_Real& Y, - Standard_Real& Z) const +void V3d_View::Convert(const Standard_Integer theXp, + const Standard_Integer theYp, + Standard_Real& theX, + Standard_Real& theY, + Standard_Real& theZ) const { V3d_UnMapped_Raise_if (!myView->IsDefined(), "view has no window"); - Standard_Integer aHeight, aWidth; + Standard_Integer aHeight = 0, aWidth = 0; MyWindow->Size (aWidth, aHeight); - Standard_Real anX = 2.0 * Xp / aWidth - 1.0; - Standard_Real anY = 2.0 * (aHeight - 1 - Yp) / aHeight - 1.0; - Standard_Real aZ = 2.0 * 0.0 - 1.0; - - gp_Pnt aResult = Camera()->UnProject (gp_Pnt (anX, anY, aZ)); - - X = aResult.X(); - Y = aResult.Y(); - Z = aResult.Z(); + const gp_Pnt anXYZ (2.0 * theXp / aWidth - 1.0, + 2.0 * (aHeight - 1 - theYp) / aHeight - 1.0, + Camera()->IsZeroToOneDepth() ? 0.0 : -1.0); + const gp_Pnt aResult = Camera()->UnProject (anXYZ); + theX = aResult.X(); + theY = aResult.Y(); + theZ = aResult.Z(); } //======================================================================= @@ -1817,7 +1815,9 @@ void V3d_View::Project (const Standard_Real theX, // NDC [-1, 1] --> PROJ [ -size / 2, +size / 2 ] theXp = aPoint.X() * aXSize * 0.5; theYp = aPoint.Y() * aYSize * 0.5; - theZp = aPoint.Z() * aZSize * 0.5; + theZp = Camera()->IsZeroToOneDepth() + ? aPoint.Z() * aZSize + : aPoint.Z() * aZSize * 0.5; } //======================================================================= diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 29b7d26ddb..09355aa4a0 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -6761,6 +6761,7 @@ static int VCaps (Draw_Interpretor& theDI, theDI << "SoftMode:" << (aCaps->contextNoAccel ? "1" : "0") << "\n"; theDI << "FFP: " << (aCaps->ffpEnable ? "1" : "0") << "\n"; theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n"; + theDI << "DepthZeroToOne: " << (aCaps->useZeroToOneDepth ? "1" : "0") << "\n"; theDI << "VSync: " << aCaps->swapInterval << "\n"; theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n"; theDI << "Stereo: " << (aCaps->contextStereo ? "1" : "0") << "\n"; @@ -6854,6 +6855,19 @@ static int VCaps (Draw_Interpretor& theDI, } aCaps->pntSpritesDisable = !toEnable; } + else if (anArgCase == "-depthzerotoone" + || anArgCase == "-zerotoonedepth" + || anArgCase == "-usezerotoonedepth" + || anArgCase == "-iszerotoonedepth") + { + Standard_Boolean toEnable = Standard_True; + if (++anArgIter < theArgNb + && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable)) + { + --anArgIter; + } + aCaps->useZeroToOneDepth = toEnable; + } else if (anArgCase == "-softmode") { Standard_Boolean toEnable = Standard_True; @@ -15072,6 +15086,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) "\n\t\t: [-vsync {0|1}] [-useWinBuffer {0|1}] [-opaqueAlpha {0|1}]" "\n\t\t: [-quadBuffer {0|1}] [-stereo {0|1}]" "\n\t\t: [-softMode {0|1}] [-noupdate|-update]" + "\n\t\t: [-zeroToOneDepth {0|1}]" "\n\t\t: [-noExtensions {0|1}] [-maxVersion Major Minor]" "\n\t\t: Modify particular graphic driver options:" "\n\t\t: sRGB - enable/disable sRGB rendering" @@ -15086,6 +15101,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) "\n\t\t: vsync - switch VSync on or off" "\n\t\t: opaqueAlpha - disable writes in alpha component of color buffer" "\n\t\t: winBuffer - allow using window buffer for rendering" + "\n\t\t: zeroToOneDepth - use [0,1] depth range instead of [-1,1] range" "\n\t\t: Context creation options:" "\n\t\t: softMode - software OpenGL implementation" "\n\t\t: compatibleProfile - backward-compatible profile" diff --git a/tests/v3d/shadows/dir3 b/tests/v3d/shadows/dir3 new file mode 100644 index 0000000000..603e77b615 --- /dev/null +++ b/tests/v3d/shadows/dir3 @@ -0,0 +1,32 @@ +puts "========" +puts "0030640: Visualization, Graphic3d_Camera - add option creating Projection matrix with 0 to 1 depth range" +puts "Test shadow map from a single directional light source on a box geometry." +puts "========" + +pload MODELING VISUALIZATION +if { $::tcl_platform(os) == "Darwin" } { vcaps -core } +vcaps -depthZeroToOne 1 +box b 1 2 3 +box bb -5 -5 0 10 10 0 -preview +vgldebug 1 +vcaps -core +vcaps -vsync 0 +vclear +vinit View1 +vrenderparams -shadingModel PHONG +vdisplay -dispMode 1 b bb +vaspects bb -material STONE +vfit +vselect 250 200 +vlight -change 0 -castShadows 1 -direction 1 1 -1 -head 0 + +vraytrace 1 +vdump $::imagedir/${::casename}_raytrace.png + +vraytrace 0 +vrenderparams -shadingModel phong +vrenderparams -shadowMapBias 0.01 +vdump $::imagedir/${::casename}_phong.png + +vrenderparams -shadingModel pbr +vdump $::imagedir/${::casename}_pbr.png