Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / shadow_map.cpp
bloba9cad04968bb280f906cf3db10a1ce027598d2ac
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/shadow_map.h"
20 #include "nel/3d/texture_mem.h"
21 #include "nel/misc/common.h"
22 #include "nel/3d/driver.h"
23 #include "nel/3d/shadow_map_manager.h"
26 using namespace std;
27 using namespace NLMISC;
29 #ifdef DEBUG_NEW
30 #define new DEBUG_NEW
31 #endif
33 namespace NL3D {
36 // ***************************************************************************
37 CShadowMap::CShadowMap(CShadowMapManager *smm)
39 nlassert(smm);
40 _ShadowMapManager= smm;
41 _TextSize= 0;
42 LastGenerationFrame= 0;
43 DistanceFade= 0;
44 TemporalOutScreenFade= 0;
45 TemporalInScreenFade= 0;
46 _FadeAround= 0;
47 _FinalFade= 1;
48 // see doc why 1.
49 InScreenFadeAccum= 1;
53 // ***************************************************************************
54 CShadowMap::~CShadowMap()
56 resetTexture();
59 // ***************************************************************************
60 void CShadowMap::initTexture(uint textSize)
62 textSize= max(textSize, 2U);
63 // if same size than setup, quit
64 if(_TextSize==textSize)
65 return;
66 resetTexture();
67 textSize= raiseToNextPowerOf2(textSize);
68 _TextSize= textSize;
70 // Allocate in the Manager.
71 _Texture= _ShadowMapManager->allocateTexture(_TextSize);
73 // Since our texture has changed, it is no more valid. reset counter.
74 LastGenerationFrame= 0;
78 // ***************************************************************************
79 void CShadowMap::resetTexture()
81 // release the SmartPtr
82 if(_Texture)
84 _ShadowMapManager->releaseTexture(_Texture);
85 _Texture= NULL;
87 _TextSize= 0;
91 // ***************************************************************************
92 void CShadowMap::buildClipInfoFromMatrix()
94 CVector vi= LocalProjectionMatrix.getI();
95 CVector vj= LocalProjectionMatrix.getJ();
96 CVector vk= LocalProjectionMatrix.getK();
97 CVector vp= LocalProjectionMatrix.getPos();
99 // **** Compute the planes.
100 LocalClipPlanes.resize(6);
101 // The plane 0 is the back plane.
102 LocalClipPlanes[0].make(-vj, vp);
103 // Left and botom plane.
104 LocalClipPlanes[1].make(-vi, vp);
105 LocalClipPlanes[2].make(-vk, vp);
106 // Right and top plane.
107 LocalClipPlanes[3].make(vi, vp + vi);
108 LocalClipPlanes[4].make(vk, vp + vk);
109 // Front plane.
110 LocalClipPlanes[5].make(vj, vp + vj);
112 // **** Compute the AA bounding box.
113 LocalBoundingBox.setHalfSize(CVector::Null);
114 CVector p0= vp;
115 CVector p1= p0 + vi + vj + vk;
116 LocalBoundingBox.setCenter(p0);
117 LocalBoundingBox.extend(p0 + vi);
118 LocalBoundingBox.extend(p0 + vj);
119 LocalBoundingBox.extend(p0 + vk);
120 LocalBoundingBox.extend(p1 - vi);
121 LocalBoundingBox.extend(p1 - vj);
122 LocalBoundingBox.extend(p1 - vk);
123 LocalBoundingBox.extend(p1);
127 // ***************************************************************************
128 void CShadowMap::buildCasterCameraMatrix(const CVector &lightDir, const CMatrix &localPosMatrix, const CAABBox &bbShape, CMatrix &cameraMatrix)
130 // compute the orthogonal LightSpace camera matrix. Remind that J look forward and K is up here.
131 cameraMatrix.setArbitraryRotJ(lightDir);
133 CAABBox bbLocal;
134 bbLocal= CAABBox::transformAABBox(cameraMatrix.inverted() * localPosMatrix, bbShape);
136 // Enlarge for 1 pixel left and right.
137 float scaleSize= (float)getTextureSize();
138 scaleSize= (scaleSize+2)/scaleSize;
139 CVector hs= bbLocal.getHalfSize();
140 hs.x*= scaleSize;
141 hs.z*= scaleSize;
142 // TestUniform
143 /*float maxLen= max(hs.x, hs.y);
144 maxLen= max(maxLen, hs.z);
145 hs.x= hs.y= hs.z= maxLen;*/
146 // EndTestUniform
147 bbLocal.setHalfSize(hs);
149 // setup the orthogonal camera Matrix so that it includes all the BBox
150 cameraMatrix.translate(bbLocal.getMin());
151 CVector vi= cameraMatrix.getI() * bbLocal.getSize().x;
152 CVector vj= cameraMatrix.getJ() * bbLocal.getSize().y;
153 CVector vk= cameraMatrix.getK() * bbLocal.getSize().z;
154 cameraMatrix.setRot(vi,vj,vk);
158 // ***************************************************************************
159 void CShadowMap::buildProjectionInfos(const CMatrix &cameraMatrix, const CVector &backPoint, float shadowMaxDepth)
161 // Modify the cameraMatrix to define the Aera of Shadow.
162 CVector projp= cameraMatrix.getPos();
163 CVector proji= cameraMatrix.getI();
164 CVector projj= cameraMatrix.getJ();
165 CVector projk= cameraMatrix.getK();
166 // modify the J vector so that it gets the Wanted Len
167 CVector vj= projj.normed();
168 projj= vj*shadowMaxDepth;
169 // Must move Pos so that the IK plane include the backPoint
170 projp+= (backPoint*vj-projp*vj) * vj;
171 // set the matrix
172 LocalProjectionMatrix.setRot(proji, projj, projk);
173 LocalProjectionMatrix.setPos(projp);
175 // compute The clipPlanes and bbox.
176 buildClipInfoFromMatrix();
180 // ***************************************************************************
181 void CShadowMap::processFades()
183 clamp(DistanceFade, 0.f, 1.f);
184 clamp(TemporalOutScreenFade, 0.f, 1.f);
185 clamp(TemporalInScreenFade, 0.f, 1.f);
187 _FadeAround= max(DistanceFade, TemporalOutScreenFade);
188 _FinalFade= max(_FadeAround, TemporalInScreenFade);
190 /* if the fadeAround is 1, then release the texture
191 Don't take _FinalFade because this last may change too much cause of TemporalInScreenFade.
192 While FadeAround is somewhat stable (as entities and the camera don't move too much),
193 TemporalInScreenFade is dependent of camera rotation.
195 => _FinalFade allow to not draw too much shadows (CPU gain),
196 while FadeAround allow in addition the capacity to not use too much texture memory
198 if(getFadeAround()==1)
199 resetTexture();
203 // ***************************************************************************
204 CShadowMapProjector::CShadowMapProjector()
206 // Trans matrix from Nel basis (Z up) to UVW basis (V up)
207 _XYZToUWVMatrix.setRot(CVector::I, CVector::K, CVector::J, true);
208 // Trans Matrix so Y is now the U (for clamp map).
209 _XYZToWUVMatrix.setRot(CVector::K, CVector::I, CVector::J, true);
212 // ***************************************************************************
213 void CShadowMapProjector::setWorldSpaceTextMat(const CMatrix &ws)
215 _WsTextMat= ws;
218 // ***************************************************************************
219 void CShadowMapProjector::applyToMaterial(const CMatrix &receiverWorldMatrix, CMaterial &material)
221 CMatrix osTextMat;
222 osTextMat.setMulMatrix(_WsTextMat, receiverWorldMatrix);
224 /* Set the TextureMatrix for ShadowMap projection so that UVW= mat * XYZ.
225 its osTextMat but must rotate so Z map to V
227 material.setUserTexMat(0, _XYZToUWVMatrix * osTextMat);
228 /* Set the TextureMatrix for ClampMap projection so that UVW= mat * XYZ.
229 its osTextMat but must rotate so Y map to U
231 material.setUserTexMat(1, _XYZToWUVMatrix * osTextMat);
235 } // NL3D