// Ryzom - 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 CL_LANDSCAPE_POLY_DRAWER_H #define CL_LANDSCAPE_POLY_DRAWER_H // Misc #include "nel/misc/aabbox.h" #include "nel/misc/polygon.h" #include "nel/misc/singleton.h" // 3D #include "nel/3d/index_buffer.h" #include "nel/3d/vertex_buffer.h" //----------------------------------------------------------------------------------------------------------- //---------------------------------------- CInitStencil ----------------------------------------------------- //----------------------------------------------------------------------------------------------------------- // CInitStencil inherits from the abstract NEL class ILandscapePolyDrawingCallback, attribut of UScene. // An instance of CInitStencil is initialized at the time of CLandscapePolyDrawer initialization // and passed to current scene. Thus, when stencil operation must be modified in a NEL class, // this instance is used with its callbacks without any NEL class knows CLandscapePolyDrawer class. //----------------------------------------------------------------------------------------------------------- class CInitStencil : public NL3D::ILandscapePolyDrawingCallback { public: // This instance is passed to current scene as its ILandscapePolyDrawingCallback instance. // (UScene::setLandscapePolyDrawingCallback is called) void init(); private: // from NL3D::ILandscapePolyDrawingCallback // This method is called before landscape render to modify stencil operation. // The eighth bit will be written with a 1 during next render. Thus we will differentiate stencil buffer parts // which will support Shadow Volume algorithm (landscape) and the other parts (veget...) virtual void beginPolyDrawing(); // from NL3D::ILandscapePolyDrawingCallback // This method is called after landscape render and before veget render to modify back stencil operation. // The eighth bit will be again written with a 0 during next render. virtual void endPolyDrawing(); }; //----------------------------------------------------------------------------------------------------------- //---------------------------------- CLandscapePolyDrawer --------------------------------------------------- //----------------------------------------------------------------------------------------------------------- // CLandscapePolyDrawer class manages display of a polygonal zones group, thanks to a Robust Shadow Volume algorithm. // To avoid intersection between a shadow volume and the frustum, the "Far" plane of this one is pushed back // to infinity during shadow volume display. // To a best robustness and to join depth range [depthMin, depthMax] used in display of main scene, an epsilon // factor is calculated to transpose Z buffer values from [depthMin, 1] to [depthMin, depthMax] // while in [depthMin, 1] depth range is used during shadow volume display. //----------------------------------------------------------------------------------------------------------- class CLandscapePolyDrawer : public NLMISC::CSingleton { public: // Constructor CLandscapePolyDrawer(); // Destructor ~CLandscapePolyDrawer(); // At every frame, polygons list is intialized and filled with addPloy calls. void addPoly(const NLMISC::CPolygon2D &poly, const NLMISC::CRGBA & color, const NLMISC::CAABBox & bBox); // At every frame end, polygons list is released. This allows an easy management to dynamic destructions, // addition or modifications of polygons. void deletePolygons(); // Compute bbox of enclosed patch of a landscape from a delimiting 2D polygon. static void computeBBoxFromPolygon(const NLMISC::CPolygon2D &poly2D, NLMISC::CAABBox &destBBox); // Called to initialize ILandscapePolyDrawingCallback instance of current scene with _InitStencil attribut. void initLandscapePolyDrawingCallback(); private: // renderScene is called in main loop. It can called beginRenderLandscapePolyPart and renderLandscapePolyPart // methods. friend void beginRenderScene(); friend void drawRenderScene(bool wantTraversals, bool keepTraversals); friend void endRenderScene(bool keepTraversals); // Enable stencil test and initialize function and operation of stencil at the beginning of renderScene method, // before opaque render of canopy and main scene parts. // The eighth bit will be written with a 0 during next render to mark stencil buffer parts which will // support Shadow Volume algorithm. void beginRenderLandscapePolyPart(); // Render polygons after opaque render of canopy and main scene parts and before transparency parts render. // ZFail algorithm is only applied to stencil buffer parts whose eighth bit is equal to 1 // (avoid to color vegetation) void renderLandscapePolyPart(); // Build vertex and index buffer of the associated polygon when addPloy is called. // Vertices coordinates aren't calculated immediately but in drawShadowVolume method, // because they are calculated in camera location. void buildShadowVolume(uint poly); // Render shadow volume of a polygon (color and depth buffers updates are disable). // This method is called twice durong the both passes of ZFail algorithm. // Coordinates of shadow volume vertex buffer are calculated in first pass. void drawShadowVolume(uint poly, bool firstPass); // Render polygon by displaying a quad which covers all zone delimited by scissor test. // This quad is applied only to stencil buffer parts whose 7 last bits aren't equal to 0, // thus the polygon projection on lanscape is delimited. void drawPolygon(uint poly); // Setup an infinite frustum and a [0, 1] depth range in a way Z Buffer values coincide // with those of main scene with the depth range of main scene. void infiniteFrustum(); // Setup initial projection matrix and depth range void finiteFrustum(); // Setup scissor delimitation for polygon void setScissor(uint polyId); // This callback allows to setup stencil operation before and after vegetables and shadow render, // in order to separate them of landscape stencil buffer values. CInitStencil * _InitStencil; // Vectors of polygons and their respective barycenters, colors, bounding boxes, // vertex and index buffers. std::vector _Polygons; std::vector _Barycenters; std::vector _PolyColor; std::vector _BBoxes; std::vector _PolyVB; std::vector _PolyIB; // Quad used to display polygons on marked parts of stencil buffer. NLMISC::CQuad _Shadow; // Initial frustum used before shadow volumes display and stored to reset old values at the end of this display. NL3D::CFrustum _FiniteFrustum; // Max depth range used before shadow volumes display and stored to reset old values back at the end of this display. float _MaxDepthRange; // View matrix used before shadow volumes display and stored to reset old values at the end of this display. NLMISC::CMatrix _OldViewMatrix; }; #endif