d84e8669 |
1 | // Copyright (c) 2021 OPEN CASCADE SAS |
2 | // |
3 | // This file is part of Open CASCADE Technology software library. |
4 | // |
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. |
10 | // |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
13 | |
14 | #include <OpenGl_ShadowMap.hxx> |
15 | |
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> |
23 | |
24 | IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShadowMap, OpenGl_NamedResource) |
25 | |
26 | // ======================================================================= |
27 | // function : OpenGl_ShadowMap |
28 | // purpose : |
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) |
35 | { |
36 | // |
37 | } |
38 | |
39 | // ======================================================================= |
40 | // function : Release |
41 | // purpose : |
42 | // ======================================================================= |
43 | void OpenGl_ShadowMap::Release (OpenGl_Context* theCtx) |
44 | { |
45 | myShadowMapFbo->Release (theCtx); |
46 | } |
47 | |
48 | // ======================================================================= |
49 | // function : ~OpenGl_ShadowMap |
50 | // purpose : |
51 | // ======================================================================= |
52 | OpenGl_ShadowMap::~OpenGl_ShadowMap() |
53 | { |
54 | Release (NULL); |
55 | } |
56 | |
57 | // ======================================================================= |
58 | // function : EstimatedDataSize |
59 | // purpose : |
60 | // ======================================================================= |
61 | Standard_Size OpenGl_ShadowMap::EstimatedDataSize() const |
62 | { |
63 | return myShadowMapFbo->EstimatedDataSize(); |
64 | } |
65 | |
66 | // ======================================================================= |
67 | // function : IsValid |
68 | // purpose : |
69 | // ======================================================================= |
70 | bool OpenGl_ShadowMap::IsValid() const |
71 | { |
72 | return myShadowMapFbo->IsValid(); |
73 | } |
74 | |
75 | // ======================================================================= |
76 | // function : Texture |
77 | // purpose : |
78 | // ======================================================================= |
79 | const Handle(OpenGl_Texture)& OpenGl_ShadowMap::Texture() const |
80 | { |
81 | return myShadowMapFbo->DepthStencilTexture(); |
82 | } |
83 | |
84 | // ======================================================================= |
85 | // function : UpdateCamera |
86 | // purpose : |
87 | // ======================================================================= |
008210c3 |
88 | bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView, |
89 | const gp_XYZ* theOrigin) |
d84e8669 |
90 | { |
008210c3 |
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) |
d84e8669 |
93 | |
94 | switch (myShadowLight->Type()) |
95 | { |
96 | case Graphic3d_TOLS_AMBIENT: |
97 | { |
98 | return false; // not applicable |
99 | } |
100 | case Graphic3d_TOLS_DIRECTIONAL: |
101 | { |
008210c3 |
102 | if (theOrigin != NULL) |
103 | { |
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); |
108 | return true; |
109 | } |
110 | |
d84e8669 |
111 | Graphic3d_Vec4d aDir (myShadowLight->Direction().X(), myShadowLight->Direction().Y(), myShadowLight->Direction().Z(), 0.0); |
112 | if (myShadowLight->IsHeadlight()) |
113 | { |
114 | Graphic3d_Mat4d anOrientInv; |
115 | theView.Camera()->OrientationMatrix().Inverted (anOrientInv); |
116 | aDir = anOrientInv * aDir; |
117 | } |
e70625d6 |
118 | myShadowCamera->SetZeroToOneDepth (theView.Camera()->IsZeroToOneDepth()); |
d84e8669 |
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()) |
122 | ? gp::DY() |
123 | : gp::DX()); |
124 | myShadowCamera->OrthogonalizeUp(); |
125 | |
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)) |
130 | { |
131 | myShadowCamera->SetScale (Max (myShadowCamera->ViewDimensions().X() * 1.1, myShadowCamera->ViewDimensions().Y() * 1.1)); // add margin |
132 | } |
133 | myShadowCamera->ZFitAll (1.0, aMinMaxBox, aGraphicBox); |
134 | myLightMatrix = myShadowCamera->ProjectionMatrixF() * myShadowCamera->OrientationMatrixF(); |
135 | return true; |
136 | } |
137 | case Graphic3d_TOLS_POSITIONAL: |
138 | { |
139 | // render into cubemap shadowmap texture |
140 | return false; // not implemented |
141 | } |
142 | case Graphic3d_TOLS_SPOT: |
143 | { |
144 | //myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective); |
145 | //myShadowCamera->SetEye (theCastShadowLight->Position()); |
146 | return false; // not implemented |
147 | } |
148 | } |
149 | return false; |
150 | } |
151 | |
152 | // ======================================================================= |
153 | // function : Release |
154 | // purpose : |
155 | // ======================================================================= |
156 | void OpenGl_ShadowMapArray::Release (OpenGl_Context* theCtx) |
157 | { |
158 | for (Standard_Integer anIter = Lower(); anIter <= Upper(); ++anIter) |
159 | { |
160 | if (const Handle(OpenGl_ShadowMap)& aShadow = ChangeValue (anIter)) |
161 | { |
162 | aShadow->Release (theCtx); |
163 | } |
164 | } |
165 | } |
166 | |
167 | // ======================================================================= |
168 | // function : EstimatedDataSize |
169 | // purpose : |
170 | // ======================================================================= |
171 | Standard_Size OpenGl_ShadowMapArray::EstimatedDataSize() const |
172 | { |
173 | Standard_Size aSize = 0; |
174 | for (Standard_Integer anIter = Lower(); anIter <= Upper(); ++anIter) |
175 | { |
176 | if (const Handle(OpenGl_ShadowMap)& aShadow = Value (anIter)) |
177 | { |
178 | aSize += aShadow->EstimatedDataSize(); |
179 | } |
180 | } |
181 | return aSize; |
182 | } |