0032129: Visualization, TKOpenGl - shadowmap is broken for ZLayer having non-zero...
authorkgv <kgv@opencascade.com>
Sat, 13 Feb 2021 22:01:27 +0000 (01:01 +0300)
committerkgv <kgv@opencascade.com>
Sat, 13 Feb 2021 22:11:37 +0000 (01:11 +0300)
OpenGl_LayerList::renderLayer() - fixed usage of wrong camera while rendering shadowmap,
and apply Z-Layer origin shift to shadowmap matrix while applying shadow.

src/OpenGl/OpenGl_BackgroundArray.cxx
src/OpenGl/OpenGl_FrameStatsPrs.cxx
src/OpenGl/OpenGl_LayerList.cxx
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_ShadowMap.cxx
src/OpenGl/OpenGl_ShadowMap.hxx
tests/v3d/shadows/double_precision [new file with mode: 0644]

index 3bde2f9d1505a83b19a5be14f94d661e8597a9df..866514d4563d7fc4c244eaaab1c4a0c78f618ab3 100644 (file)
@@ -449,13 +449,13 @@ void OpenGl_BackgroundArray::Render (const Handle(OpenGl_Workspace)& theWorkspac
   Standard_Integer aViewSizeY = aCtx->Viewport()[3];
   Graphic3d_Vec2i aTileOffset, aTileSize;
 
-  if (theWorkspace->View()->Camera()->Tile().IsValid())
+  if (aCtx->Camera()->Tile().IsValid())
   {
-    aViewSizeX = theWorkspace->View()->Camera()->Tile().TotalSize.x();
-    aViewSizeY = theWorkspace->View()->Camera()->Tile().TotalSize.y();
+    aViewSizeX = aCtx->Camera()->Tile().TotalSize.x();
+    aViewSizeY = aCtx->Camera()->Tile().TotalSize.y();
 
-    aTileOffset = theWorkspace->View()->Camera()->Tile().OffsetLowerLeft();
-    aTileSize   = theWorkspace->View()->Camera()->Tile().TileSize;
+    aTileOffset = aCtx->Camera()->Tile().OffsetLowerLeft();
+    aTileSize   = aCtx->Camera()->Tile().TileSize;
   }
   if (myToUpdate
    || myViewWidth  != aViewSizeX
@@ -473,7 +473,7 @@ void OpenGl_BackgroundArray::Render (const Handle(OpenGl_Workspace)& theWorkspac
 
   if (myType == Graphic3d_TOB_CUBEMAP)
   {
-    Graphic3d_Camera aCamera (theWorkspace->View()->Camera());
+    Graphic3d_Camera aCamera (aCtx->Camera());
     aCamera.SetZRange (0.01, 1.0); // is needed to avoid perspective camera exception
 
     // cancel translation
@@ -514,7 +514,7 @@ void OpenGl_BackgroundArray::Render (const Handle(OpenGl_Workspace)& theWorkspac
   {
     aProjection.InitIdentity();
     aWorldView.InitIdentity();
-    if (theWorkspace->View()->Camera()->Tile().IsValid())
+    if (aCtx->Camera()->Tile().IsValid())
     {
       aWorldView.SetDiagonal (OpenGl_Vec4 (2.0f / aTileSize.x(), 2.0f / aTileSize.y(), 1.0f, 1.0f));
       if (myType == Graphic3d_TOB_GRADIENT)
index 95a5d3b55f0c4df79ede98de040af0ebf174b4e6..664317b87f8c7979b7d83d90d1245e58238d250a 100644 (file)
@@ -405,7 +405,7 @@ void OpenGl_FrameStatsPrs::Render (const Handle(OpenGl_Workspace)& theWorkspace)
     aCtx->WorldViewState.Push();
     if (!myChartTrsfPers.IsNull())
     {
-      myChartTrsfPers->Apply (theWorkspace->View()->Camera(),
+      myChartTrsfPers->Apply (aCtx->Camera(),
                               aCtx->ProjectionState.Current(), aCtx->WorldViewState.ChangeCurrent(),
                               aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]);
     }
index 79b32cc78985653c019dc9220d7eba31047059e2..563bc6726b40b6eb37465c313f5a42e6f785ee31 100644 (file)
@@ -20,6 +20,7 @@
 #include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_LayerList.hxx>
 #include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_ShadowMap.hxx>
 #include <OpenGl_Structure.hxx>
 #include <OpenGl_VertexBuffer.hxx>
 #include <OpenGl_View.hxx>
@@ -604,7 +605,7 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
     aManager->UpdateLightSourceStateTo (aLayerSettings.Lights(), theWorkspace->View()->SpecIBLMapLevels(), Handle(OpenGl_ShadowMapArray)());
   }
 
-  const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera();
+  const Handle(Graphic3d_Camera)& aWorldCamera = aCtx->Camera();
   if (hasLocalCS)
   {
     // Apply local camera transformation.
@@ -645,6 +646,15 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
     NCollection_Mat4<Standard_Real> aWorldView = aWorldCamera->OrientationMatrix();
     Graphic3d_TransformUtils::Translate (aWorldView, aLayerSettings.Origin().X(), aLayerSettings.Origin().Y(), aLayerSettings.Origin().Z());
 
+    if (!aManager->LightSourceState().ShadowMaps().IsNull())
+    {
+      // shift shadowmap matrix
+      for (OpenGl_ShadowMapArray::Iterator aShadowIter (*aManager->LightSourceState().ShadowMaps()); aShadowIter.More(); aShadowIter.Next())
+      {
+        aShadowIter.Value()->UpdateCamera (*theWorkspace->View(), &aLayerSettings.Origin());
+      }
+    }
+
     NCollection_Mat4<Standard_ShortReal> aWorldViewF;
     aWorldViewF.ConvertFrom (aWorldView);
     aCtx->WorldViewState.SetCurrent (aWorldViewF);
@@ -676,6 +686,15 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
   }
   if (hasLocalCS)
   {
+    if (!aManager->LightSourceState().ShadowMaps().IsNull())
+    {
+      // restore shadowmap matrix
+      for (OpenGl_ShadowMapArray::Iterator aShadowIter (*aManager->LightSourceState().ShadowMaps()); aShadowIter.More(); aShadowIter.Next())
+      {
+        aShadowIter.Value()->UpdateCamera (*theWorkspace->View(), &gp::Origin().XYZ());
+      }
+    }
+
     aCtx->ShaderManager()->RevertClippingState();
     aCtx->ShaderManager()->UpdateLightSourceState();
 
index e024d39946c268e8e2e15ccb58ba3ba1f54fc191..88c251939065e6ba0c7c081d38899ca00fa15518 100644 (file)
@@ -1037,7 +1037,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
       const Graphic3d_Vec2i aViewSize (aCtx->Viewport()[2], aCtx->Viewport()[3]);
       const Standard_Integer aMin = aViewSize.minComp();
       const GLfloat anEdgeWidth  = (GLfloat )anAspectFace->Aspect()->EdgeWidth() * aCtx->LineWidthScale() / (GLfloat )aMin;
-      const GLfloat anOrthoScale = theWorkspace->View()->Camera()->IsOrthographic() ? (GLfloat )theWorkspace->View()->Camera()->Scale() : -1.0f;
+      const GLfloat anOrthoScale = aCtx->Camera()->IsOrthographic() ? (GLfloat )aCtx->Camera()->Scale() : -1.0f;
 
       const Handle(OpenGl_ShaderProgram)& anOutlineProgram = aCtx->ActiveProgram();
       anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_SILHOUETTE_THICKNESS), anEdgeWidth);
index 53d0a8b79203c604bc1418ddd545c3be3f90a185..c1db3db21a7af9a01a62aa6b8d8906fed5a4aa93 100644 (file)
@@ -85,10 +85,11 @@ const Handle(OpenGl_Texture)& OpenGl_ShadowMap::Texture() const
 // function : UpdateCamera
 // purpose  :
 // =======================================================================
-bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView)
+bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView,
+                                     const gp_XYZ* theOrigin)
 {
-  const Bnd_Box aMinMaxBox  = theView.MinMaxValues (false); // applicative min max boundaries
-  const Bnd_Box aGraphicBox = theView.MinMaxValues (true);  // real graphical boundaries (not accounting infinite flag).
+  const Bnd_Box aMinMaxBox  = theOrigin == NULL ? theView.MinMaxValues (false) : Bnd_Box(); // applicative min max boundaries
+  const Bnd_Box aGraphicBox = theOrigin == NULL ? theView.MinMaxValues (true)  : Bnd_Box(); // real graphical boundaries (not accounting infinite flag)
 
   switch (myShadowLight->Type())
   {
@@ -98,6 +99,15 @@ bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView)
     }
     case Graphic3d_TOLS_DIRECTIONAL:
     {
+      if (theOrigin != NULL)
+      {
+        Graphic3d_Mat4d aTrans;
+        aTrans.Translate (Graphic3d_Vec3d (theOrigin->X(), theOrigin->Y(), theOrigin->Z()));
+        Graphic3d_Mat4d anOrientMat = myShadowCamera->OrientationMatrix() * aTrans;
+        myLightMatrix = myShadowCamera->ProjectionMatrixF() * Graphic3d_Mat4 (anOrientMat);
+        return true;
+      }
+
       Graphic3d_Vec4d aDir (myShadowLight->Direction().X(), myShadowLight->Direction().Y(), myShadowLight->Direction().Z(), 0.0);
       if (myShadowLight->IsHeadlight())
       {
index d192c7a868a7f6e0a74c2707c7dfa7599fc9fb80..0aa2698a6cb78d96a1749b50d75fe7fe77771d10 100644 (file)
@@ -19,6 +19,7 @@
 #include <NCollection_Shared.hxx>
 #include <OpenGl_NamedResource.hxx>
 
+class gp_XYZ;
 class Graphic3d_Camera;
 class Graphic3d_CLight;
 class Graphic3d_CView;
@@ -74,7 +75,10 @@ public:
   void SetShadowMapBias (Standard_ShortReal theBias) { myShadowMapBias = theBias; }
 
   //! Compute camera.
-  Standard_EXPORT bool UpdateCamera (const Graphic3d_CView& theView);
+  //! @param theView   [in] active view
+  //! @param theOrigin [in] when not-NULL - displace shadow map camera to specified Z-Layer origin
+  Standard_EXPORT bool UpdateCamera (const Graphic3d_CView& theView,
+                                     const gp_XYZ* theOrigin = NULL);
 
 private:
 
diff --git a/tests/v3d/shadows/double_precision b/tests/v3d/shadows/double_precision
new file mode 100644 (file)
index 0000000..34180aa
--- /dev/null
@@ -0,0 +1,23 @@
+puts "========"
+puts "0032129: Visualization, TKOpenGl - shadowmap is broken for ZLayer having non-zero origin"
+puts "========"
+
+pload MODELING VISUALIZATION
+box b  0 0 1 100 200 300
+box bb -500 -500 0 1000 1000 0 -preview
+vinit View1
+vrenderparams -shadingModel PHONG
+vdisplay -dispMode 1 b bb
+vaspects bb -material STONE
+vfit
+vlight -change 0 -castShadows 1 -head 0 -dir 1 1 -1
+vdump $::imagedir/${::casename}_1.png
+vzlayer DEFAULT -origin 200 0 0
+vdump $::imagedir/${::casename}_2.png
+
+vlocation b  -setLocation 1000000000 0 0
+vlocation bb -setLocation 1000000000 0 0
+vfit
+vdump $::imagedir/${::casename}_3.png
+vzlayer DEFAULT   -origin 1000000000 0 0
+vdump $::imagedir/${::casename}_4.png