1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #ifndef CL_LANDSCAPE_POLY_DRAWER_H
21 #define CL_LANDSCAPE_POLY_DRAWER_H
24 #include "nel/misc/aabbox.h"
25 #include "nel/misc/polygon.h"
26 #include "nel/misc/singleton.h"
29 #include "nel/3d/index_buffer.h"
30 #include "nel/3d/vertex_buffer.h"
33 //-----------------------------------------------------------------------------------------------------------
34 //---------------------------------------- CInitStencil -----------------------------------------------------
35 //-----------------------------------------------------------------------------------------------------------
36 // CInitStencil inherits from the abstract NEL class ILandscapePolyDrawingCallback, attribut of UScene.
37 // An instance of CInitStencil is initialized at the time of CLandscapePolyDrawer initialization
38 // and passed to current scene. Thus, when stencil operation must be modified in a NEL class,
39 // this instance is used with its callbacks without any NEL class knows CLandscapePolyDrawer class.
40 //-----------------------------------------------------------------------------------------------------------
41 class CInitStencil
: public NL3D::ILandscapePolyDrawingCallback
46 // This instance is passed to current scene as its ILandscapePolyDrawingCallback instance.
47 // (UScene::setLandscapePolyDrawingCallback is called)
51 // from NL3D::ILandscapePolyDrawingCallback
52 // This method is called before landscape render to modify stencil operation.
53 // The eighth bit will be written with a 1 during next render. Thus we will differentiate stencil buffer parts
54 // which will support Shadow Volume algorithm (landscape) and the other parts (veget...)
55 virtual void beginPolyDrawing();
57 // from NL3D::ILandscapePolyDrawingCallback
58 // This method is called after landscape render and before veget render to modify back stencil operation.
59 // The eighth bit will be again written with a 0 during next render.
60 virtual void endPolyDrawing();
64 //-----------------------------------------------------------------------------------------------------------
65 //---------------------------------- CLandscapePolyDrawer ---------------------------------------------------
66 //-----------------------------------------------------------------------------------------------------------
67 // CLandscapePolyDrawer class manages display of a polygonal zones group, thanks to a Robust Shadow Volume algorithm.
68 // To avoid intersection between a shadow volume and the frustum, the "Far" plane of this one is pushed back
69 // to infinity during shadow volume display.
70 // To a best robustness and to join depth range [depthMin, depthMax] used in display of main scene, an epsilon
71 // factor is calculated to transpose Z buffer values from [depthMin, 1] to [depthMin, depthMax]
72 // while in [depthMin, 1] depth range is used during shadow volume display.
73 //-----------------------------------------------------------------------------------------------------------
74 class CLandscapePolyDrawer
: public NLMISC::CSingleton
<CLandscapePolyDrawer
>
80 CLandscapePolyDrawer();
83 ~CLandscapePolyDrawer();
85 // At every frame, polygons list is intialized and filled with addPloy calls.
86 void addPoly(const NLMISC::CPolygon2D
&poly
, const NLMISC::CRGBA
& color
, const NLMISC::CAABBox
& bBox
);
88 // At every frame end, polygons list is released. This allows an easy management to dynamic destructions,
89 // addition or modifications of polygons.
90 void deletePolygons();
92 // Compute bbox of enclosed patch of a landscape from a delimiting 2D polygon.
93 static void computeBBoxFromPolygon(const NLMISC::CPolygon2D
&poly2D
, NLMISC::CAABBox
&destBBox
);
95 // Called to initialize ILandscapePolyDrawingCallback instance of current scene with _InitStencil attribut.
96 void initLandscapePolyDrawingCallback();
101 // renderScene is called in main loop. It can called beginRenderLandscapePolyPart and renderLandscapePolyPart
103 friend void beginRenderScene();
104 friend void drawRenderScene(bool wantTraversals
, bool keepTraversals
);
105 friend void endRenderScene(bool keepTraversals
);
107 // Enable stencil test and initialize function and operation of stencil at the beginning of renderScene method,
108 // before opaque render of canopy and main scene parts.
109 // The eighth bit will be written with a 0 during next render to mark stencil buffer parts which will
110 // support Shadow Volume algorithm.
111 void beginRenderLandscapePolyPart();
113 // Render polygons after opaque render of canopy and main scene parts and before transparency parts render.
114 // ZFail algorithm is only applied to stencil buffer parts whose eighth bit is equal to 1
115 // (avoid to color vegetation)
116 void renderLandscapePolyPart();
118 // Build vertex and index buffer of the associated polygon when addPloy is called.
119 // Vertices coordinates aren't calculated immediately but in drawShadowVolume method,
120 // because they are calculated in camera location.
121 void buildShadowVolume(uint poly
);
123 // Render shadow volume of a polygon (color and depth buffers updates are disable).
124 // This method is called twice durong the both passes of ZFail algorithm.
125 // Coordinates of shadow volume vertex buffer are calculated in first pass.
126 void drawShadowVolume(uint poly
, bool firstPass
);
128 // Render polygon by displaying a quad which covers all zone delimited by scissor test.
129 // This quad is applied only to stencil buffer parts whose 7 last bits aren't equal to 0,
130 // thus the polygon projection on lanscape is delimited.
131 void drawPolygon(uint poly
);
133 // Setup an infinite frustum and a [0, 1] depth range in a way Z Buffer values coincide
134 // with those of main scene with the depth range of main scene.
135 void infiniteFrustum();
137 // Setup initial projection matrix and depth range
138 void finiteFrustum();
140 // Setup scissor delimitation for polygon
141 void setScissor(uint polyId
);
144 // This callback allows to setup stencil operation before and after vegetables and shadow render,
145 // in order to separate them of landscape stencil buffer values.
146 CInitStencil
* _InitStencil
;
148 // Vectors of polygons and their respective barycenters, colors, bounding boxes,
149 // vertex and index buffers.
150 std::vector
<NLMISC::CPolygon2D
> _Polygons
;
151 std::vector
<NLMISC::CVector2f
> _Barycenters
;
152 std::vector
<NLMISC::CRGBA
> _PolyColor
;
153 std::vector
<NLMISC::CAABBox
> _BBoxes
;
155 std::vector
<NL3D::CVertexBuffer
> _PolyVB
;
156 std::vector
<NL3D::CIndexBuffer
> _PolyIB
;
158 // Quad used to display polygons on marked parts of stencil buffer.
159 NLMISC::CQuad _Shadow
;
161 // Initial frustum used before shadow volumes display and stored to reset old values at the end of this display.
162 NL3D::CFrustum _FiniteFrustum
;
164 // Max depth range used before shadow volumes display and stored to reset old values back at the end of this display.
165 float _MaxDepthRange
;
167 // View matrix used before shadow volumes display and stored to reset old values at the end of this display.
168 NLMISC::CMatrix _OldViewMatrix
;