0032129: Visualization, TKOpenGl - shadowmap is broken for ZLayer having non-zero...
[occt.git] / src / OpenGl / OpenGl_ShadowMap.cxx
CommitLineData
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
24IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShadowMap, OpenGl_NamedResource)
25
26// =======================================================================
27// function : OpenGl_ShadowMap
28// purpose :
29// =======================================================================
30OpenGl_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// =======================================================================
43void OpenGl_ShadowMap::Release (OpenGl_Context* theCtx)
44{
45 myShadowMapFbo->Release (theCtx);
46}
47
48// =======================================================================
49// function : ~OpenGl_ShadowMap
50// purpose :
51// =======================================================================
52OpenGl_ShadowMap::~OpenGl_ShadowMap()
53{
54 Release (NULL);
55}
56
57// =======================================================================
58// function : EstimatedDataSize
59// purpose :
60// =======================================================================
61Standard_Size OpenGl_ShadowMap::EstimatedDataSize() const
62{
63 return myShadowMapFbo->EstimatedDataSize();
64}
65
66// =======================================================================
67// function : IsValid
68// purpose :
69// =======================================================================
70bool OpenGl_ShadowMap::IsValid() const
71{
72 return myShadowMapFbo->IsValid();
73}
74
75// =======================================================================
76// function : Texture
77// purpose :
78// =======================================================================
79const Handle(OpenGl_Texture)& OpenGl_ShadowMap::Texture() const
80{
81 return myShadowMapFbo->DepthStencilTexture();
82}
83
84// =======================================================================
85// function : UpdateCamera
86// purpose :
87// =======================================================================
008210c3 88bool 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 }
118 myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
119 myShadowCamera->SetDirection (gp_Dir (aDir.x(), aDir.y(), aDir.z()));
120 myShadowCamera->SetUp (!myShadowCamera->Direction().IsParallel (gp::DY(), Precision::Angular())
121 ? gp::DY()
122 : gp::DX());
123 myShadowCamera->OrthogonalizeUp();
124
125 // Fitting entire scene to the light might produce a shadow map of too low resolution.
126 // More reliable approach would be putting a center to a current eye position and limiting maximum range,
127 // so that shadow range will be limited to some reasonable distance from current eye.
128 if (myShadowCamera->FitMinMax (aMinMaxBox, 10.0 * Precision::Confusion(), false))
129 {
130 myShadowCamera->SetScale (Max (myShadowCamera->ViewDimensions().X() * 1.1, myShadowCamera->ViewDimensions().Y() * 1.1)); // add margin
131 }
132 myShadowCamera->ZFitAll (1.0, aMinMaxBox, aGraphicBox);
133 myLightMatrix = myShadowCamera->ProjectionMatrixF() * myShadowCamera->OrientationMatrixF();
134 return true;
135 }
136 case Graphic3d_TOLS_POSITIONAL:
137 {
138 // render into cubemap shadowmap texture
139 return false; // not implemented
140 }
141 case Graphic3d_TOLS_SPOT:
142 {
143 //myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
144 //myShadowCamera->SetEye (theCastShadowLight->Position());
145 return false; // not implemented
146 }
147 }
148 return false;
149}
150
151// =======================================================================
152// function : Release
153// purpose :
154// =======================================================================
155void OpenGl_ShadowMapArray::Release (OpenGl_Context* theCtx)
156{
157 for (Standard_Integer anIter = Lower(); anIter <= Upper(); ++anIter)
158 {
159 if (const Handle(OpenGl_ShadowMap)& aShadow = ChangeValue (anIter))
160 {
161 aShadow->Release (theCtx);
162 }
163 }
164}
165
166// =======================================================================
167// function : EstimatedDataSize
168// purpose :
169// =======================================================================
170Standard_Size OpenGl_ShadowMapArray::EstimatedDataSize() const
171{
172 Standard_Size aSize = 0;
173 for (Standard_Integer anIter = Lower(); anIter <= Upper(); ++anIter)
174 {
175 if (const Handle(OpenGl_ShadowMap)& aShadow = Value (anIter))
176 {
177 aSize += aShadow->EstimatedDataSize();
178 }
179 }
180 return aSize;
181}