// NeL - MMORPG Framework // 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 . #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 */ 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 LocalClipPlanes; /** Computed at shadow casting time. This is the LocalPos Bouding Box containing the shadow (AxisAligned). * \see generateClipInfoFromMatrix() */ 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 CVector &lightDir, const CMatrix &localPosMatrix, const CAABBox &bbShape, 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 CMatrix &cameraMatrix, const 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 _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 CMatrix &ws); void applyToMaterial(const CMatrix &receiverWorldMatrix, CMaterial &material); private: CMatrix _WsTextMat; CMatrix _XYZToUWVMatrix; CMatrix _XYZToWUVMatrix; }; } // NL3D #endif // NL_SHADOW_MAP_H /* End of shadow_map.h */