1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
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"
27 using namespace NLMISC
;
36 // ***************************************************************************
37 CShadowMap::CShadowMap(CShadowMapManager
*smm
)
40 _ShadowMapManager
= smm
;
42 LastGenerationFrame
= 0;
44 TemporalOutScreenFade
= 0;
45 TemporalInScreenFade
= 0;
53 // ***************************************************************************
54 CShadowMap::~CShadowMap()
59 // ***************************************************************************
60 void CShadowMap::initTexture(uint textSize
)
62 textSize
= max(textSize
, 2U);
63 // if same size than setup, quit
64 if(_TextSize
==textSize
)
67 textSize
= raiseToNextPowerOf2(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
84 _ShadowMapManager
->releaseTexture(_Texture
);
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
);
110 LocalClipPlanes
[5].make(vj
, vp
+ vj
);
112 // **** Compute the AA bounding box.
113 LocalBoundingBox
.setHalfSize(CVector::Null
);
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
);
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();
143 /*float maxLen= max(hs.x, hs.y);
144 maxLen= max(maxLen, hs.z);
145 hs.x= hs.y= hs.z= maxLen;*/
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
;
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)
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
)
218 // ***************************************************************************
219 void CShadowMapProjector::applyToMaterial(const CMatrix
&receiverWorldMatrix
, CMaterial
&material
)
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
);