1 // Copyright (c) 2021 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <OpenGl_ShadowMap.hxx>
16 #include <OpenGl_ArbFBO.hxx>
17 #include <OpenGl_FrameBuffer.hxx>
18 #include <OpenGl_ShaderManager.hxx>
19 #include <Graphic3d_Camera.hxx>
20 #include <Graphic3d_CView.hxx>
21 #include <Message.hxx>
22 #include <Message_Messenger.hxx>
24 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShadowMap, OpenGl_NamedResource)
26 // =======================================================================
27 // function : OpenGl_ShadowMap
29 // =======================================================================
30 OpenGl_ShadowMap::OpenGl_ShadowMap()
31 : OpenGl_NamedResource ("shadow_map"),
32 myShadowMapFbo (new OpenGl_FrameBuffer()),
33 myShadowCamera (new Graphic3d_Camera()),
34 myShadowMapBias (0.0f)
39 // =======================================================================
42 // =======================================================================
43 void OpenGl_ShadowMap::Release (OpenGl_Context* theCtx)
45 myShadowMapFbo->Release (theCtx);
48 // =======================================================================
49 // function : ~OpenGl_ShadowMap
51 // =======================================================================
52 OpenGl_ShadowMap::~OpenGl_ShadowMap()
57 // =======================================================================
58 // function : EstimatedDataSize
60 // =======================================================================
61 Standard_Size OpenGl_ShadowMap::EstimatedDataSize() const
63 return myShadowMapFbo->EstimatedDataSize();
66 // =======================================================================
69 // =======================================================================
70 bool OpenGl_ShadowMap::IsValid() const
72 return myShadowMapFbo->IsValid();
75 // =======================================================================
78 // =======================================================================
79 const Handle(OpenGl_Texture)& OpenGl_ShadowMap::Texture() const
81 return myShadowMapFbo->DepthStencilTexture();
84 // =======================================================================
85 // function : UpdateCamera
87 // =======================================================================
88 bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView,
89 const gp_XYZ* theOrigin)
91 const Bnd_Box aMinMaxBox = theOrigin == NULL ? theView.MinMaxValues (false) : Bnd_Box(); // applicative min max boundaries
92 const Bnd_Box aGraphicBox = theOrigin == NULL ? theView.MinMaxValues (true) : Bnd_Box(); // real graphical boundaries (not accounting infinite flag)
94 switch (myShadowLight->Type())
96 case Graphic3d_TOLS_AMBIENT:
98 return false; // not applicable
100 case Graphic3d_TOLS_DIRECTIONAL:
102 if (theOrigin != NULL)
104 Graphic3d_Mat4d aTrans;
105 aTrans.Translate (Graphic3d_Vec3d (theOrigin->X(), theOrigin->Y(), theOrigin->Z()));
106 Graphic3d_Mat4d anOrientMat = myShadowCamera->OrientationMatrix() * aTrans;
107 myLightMatrix = myShadowCamera->ProjectionMatrixF() * Graphic3d_Mat4 (anOrientMat);
111 Graphic3d_Vec4d aDir (myShadowLight->Direction().X(), myShadowLight->Direction().Y(), myShadowLight->Direction().Z(), 0.0);
112 if (myShadowLight->IsHeadlight())
114 Graphic3d_Mat4d anOrientInv;
115 theView.Camera()->OrientationMatrix().Inverted (anOrientInv);
116 aDir = anOrientInv * aDir;
118 myShadowCamera->SetZeroToOneDepth (theView.Camera()->IsZeroToOneDepth());
119 myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
120 myShadowCamera->SetDirection (gp_Dir (aDir.x(), aDir.y(), aDir.z()));
121 myShadowCamera->SetUp (!myShadowCamera->Direction().IsParallel (gp::DY(), Precision::Angular())
124 myShadowCamera->OrthogonalizeUp();
126 // Fitting entire scene to the light might produce a shadow map of too low resolution.
127 // More reliable approach would be putting a center to a current eye position and limiting maximum range,
128 // so that shadow range will be limited to some reasonable distance from current eye.
129 if (myShadowCamera->FitMinMax (aMinMaxBox, 10.0 * Precision::Confusion(), false))
131 myShadowCamera->SetScale (Max (myShadowCamera->ViewDimensions().X() * 1.1, myShadowCamera->ViewDimensions().Y() * 1.1)); // add margin
133 myShadowCamera->ZFitAll (1.0, aMinMaxBox, aGraphicBox);
134 myLightMatrix = myShadowCamera->ProjectionMatrixF() * myShadowCamera->OrientationMatrixF();
137 case Graphic3d_TOLS_POSITIONAL:
139 // render into cubemap shadowmap texture
140 return false; // not implemented
142 case Graphic3d_TOLS_SPOT:
144 //myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
145 //myShadowCamera->SetEye (theCastShadowLight->Position());
146 return false; // not implemented
152 // =======================================================================
153 // function : Release
155 // =======================================================================
156 void OpenGl_ShadowMapArray::Release (OpenGl_Context* theCtx)
158 for (Standard_Integer anIter = Lower(); anIter <= Upper(); ++anIter)
160 if (const Handle(OpenGl_ShadowMap)& aShadow = ChangeValue (anIter))
162 aShadow->Release (theCtx);
167 // =======================================================================
168 // function : EstimatedDataSize
170 // =======================================================================
171 Standard_Size OpenGl_ShadowMapArray::EstimatedDataSize() const
173 Standard_Size aSize = 0;
174 for (Standard_Integer anIter = Lower(); anIter <= Upper(); ++anIter)
176 if (const Handle(OpenGl_ShadowMap)& aShadow = Value (anIter))
178 aSize += aShadow->EstimatedDataSize();