khanat-opennel-code/code/nel/include/nel/3d/shadow_map.h
2016-12-04 17:32:34 +01:00

176 lines
6.4 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_SHADOW_MAP_H
#define NL_SHADOW_MAP_H
#include "nel/misc/types_nl.h"
#include "nel/3d/texture.h"
#include "nel/3d/vertex_buffer.h"
#include "nel/misc/aabbox.h"
namespace NL3D
{
using NLMISC::CPlane;
using NLMISC::CRefPtr;
using NLMISC::CAABBox;
class CShadowMapManager;
class CMaterial;
// ***************************************************************************
/**
* This class encapsulate all Data generated by a Shadow Caster, and read for a Shadow Receiver.
* \author Lionel Berenguier
* \author Nevrax France
* \date 2003
*/
class CShadowMap
{
public:
/** Computed at shadow casting time. The matrix used to cast the Shadow.
* It is actualy a World ProjectionMatrix, but is only local to the Position of the Model (not rotation/scale).
* Hence receiver have to add the position of the caster model to this matrix to get true World.
* The usage of this matrix is for UV projection: XYZ= WorldProjectionMatrix * UVW.
* NB: Vj (ie for W) is mapped such that Vp means NearClip of the shadow and Vp+Vj means FarClip of the shadow
*/
NLMISC::CMatrix LocalProjectionMatrix;
/** Computed at shadow casting time. They are clipping planes used to clip receivers (mirror of the OBB).
* Receivers may use them to clip sub received parts (as they which)
* Like the ProjectionLocalMatrix, this plane are in World, but the position of the Caster model.
* \see generateClipInfoFromMatrix()
*/
std::vector<CPlane> LocalClipPlanes;
/** Computed at shadow casting time. This is the LocalPos Bouding Box containing the shadow (AxisAligned).
* \see generateClipInfoFromMatrix()
*/
NLMISC::CAABBox LocalBoundingBox;
// Filled by ShadowMapManager. This is the Last Frame Id we had update the texture.
uint64 LastGenerationFrame;
/** They are the fade of the shadowMap, for Lod Shadow display. 0-1 values.
* NB: if DistanceFade==1 or TemporalOutScreenFade==1, then the ShadowMap Texture is released.
* Final Fade is the max of the 3.
*/
// Value computed according to pos of skeleton and Max Shadow Display value.
float DistanceFade;
// Value computed according to pos of skeleton and other skeletons in the area (whatever the visible state)
float TemporalOutScreenFade;
// Value computed according to pos of skeleton and other skeletons in the frustum
float TemporalInScreenFade;
/** This value represent the fade time we don't know what to do with TemporalInScreenFade because the
* shadowMap is not visible or frustum-clipped.
* Once the shadowMap will be visible again, This will be add/removed (according to TemporalInScreenFade
* rules) to the TemporalInScreenFade.
* NB: by default the value is 1 so the initial state is correct when you enable cast shadowMap!
*/
float InScreenFadeAccum;
public:
/// Constructor. NB: ptr is owned => shadowMap should no still live while smm dead.
CShadowMap(CShadowMapManager *smm);
~CShadowMap();
/// create the Texture. It reset the texture if not of same size.
void initTexture(uint textSize);
/// reset the Texture
void resetTexture();
/// get the TextureSize
uint32 getTextureSize() const {return _TextSize;}
/// You can only get the texture for filling / use in a material.
ITexture *getTexture() const {return _Texture;}
/// /name Tools
// @{
/** From A BBox in Object Space, the lightDir, and the (nearly) worldMatrix, build the Camera for common Render Projection
* The caller has then just to do
* driver->setFrustum(0,1,0,1,0,1,false);
* driver->setupViewMatrix(cameraMatrix.inverted());
* driver->setupModelMatrix(localPosMatrix);
* Then render his mesh.
*/
void buildCasterCameraMatrix(const NLMISC::CVector &lightDir, const NLMISC::CMatrix &localPosMatrix, const NLMISC::CAABBox &bbShape, NLMISC::CMatrix &cameraMatrix);
/** From the Camera matrix computed with buildCasterCameraMatrix, compute the LocalProjectionMatrix, which modify the
* J axis according to backPoint and Shadow Depth.
* NB: automatically calls the buildClipInfoFromMatrix() method
*/
void buildProjectionInfos(const NLMISC::CMatrix &cameraMatrix, const NLMISC::CVector &backPoint, float shadowMaxDepth);
/** The ShadowMap Caster can call this method after setting LocalProjectionMatrix. It computes auto the
* LocalClipPlanes and LocalBoundingBox from it. NB: don't use it if you use buildProjectionInfos().
*/
void buildClipInfoFromMatrix();
// @}
/** Clamp Fades to 0-1. Additionaly reset the texture if DistanceFade>=1 or TemporalOutScreenFade>=1
* See Implementation for Why. Additionally compile getFadeAround() and getFadeInScreen()
*/
void processFades();
/// return compiled max of DistanceFade and TemporalOutScreenFade.
float getFadeAround() const {return _FadeAround;}
/// same but maximize with the TemporalInScreenFade;
float getFinalFade() const {return _FinalFade;}
// *************
private:
NLMISC::CSmartPtr<ITexture> _Texture;
uint32 _TextSize;
CShadowMapManager *_ShadowMapManager;
float _FadeAround;
float _FinalFade;
};
// ***************************************************************************
/** Used to recompute the projection matrix, according to the receiver worldMatrix
* The problem is material don't support WorldSpace Coordinate Generation, but ObjectSpace ones.
* Hence must take back the coordinate in ObjectSpace before set textMat.
*/
class CShadowMapProjector
{
public:
CShadowMapProjector();
void setWorldSpaceTextMat(const NLMISC::CMatrix &ws);
void applyToMaterial(const NLMISC::CMatrix &receiverWorldMatrix, CMaterial &material);
private:
NLMISC::CMatrix _WsTextMat;
NLMISC::CMatrix _XYZToUWVMatrix;
NLMISC::CMatrix _XYZToWUVMatrix;
};
} // NL3D
#endif // NL_SHADOW_MAP_H
/* End of shadow_map.h */