1 /** @file drawlist.h  Drawable primitive list.
2  *
3  * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  * @authors Copyright © 2006-2015 Daniel Swanson <danij@dengine.net>
5  *
6  * @par License
7  * GPL: http://www.gnu.org/licenses/gpl.html
8  *
9  * <small>This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by the
11  * Free Software Foundation; either version 2 of the License, or (at your
12  * option) any later version. This program is distributed in the hope that it
13  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details. You should have received a copy of the GNU
16  * General Public License along with this program; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA</small>
19  */
20 
21 #ifndef CLIENT_RENDER_DRAWLIST_H
22 #define CLIENT_RENDER_DRAWLIST_H
23 
24 #include <array>
25 #include <QFlags>
26 #include <de/GLBuffer>
27 #include <de/Vector>
28 #include "api_gl.h" // blendmode_e
29 #include "gl/gltextureunit.h"
30 
31 struct Store;
32 
33 /// Semantic geometry group identifiers.
34 enum GeomGroup
35 {
36     UnlitGeom = 0,  ///< Normal, unlit geometries.
37     LitGeom,        ///< Normal, lit goemetries.
38     SkyMaskGeom,    ///< Sky mask geometries.
39     LightGeom,      ///< Dynamic light geometries.
40     ShadowGeom,     ///< Map object and/or Fake Radio shadow geometries.
41     ShineGeom       ///< Surface reflection geometries.
42 };
43 
44 /// Logical drawing modes.
45 enum DrawMode
46 {
47     DM_SKYMASK,
48     DM_ALL,
49     DM_LIGHT_MOD_TEXTURE,
50     DM_FIRST_LIGHT,
51     DM_TEXTURE_PLUS_LIGHT,
52     DM_UNBLENDED_TEXTURE_AND_DETAIL,
53     DM_BLENDED,
54     DM_BLENDED_FIRST_LIGHT,
55     DM_NO_LIGHTS,
56     DM_WITHOUT_TEXTURE,
57     DM_LIGHTS,
58     DM_MOD_TEXTURE,
59     DM_MOD_TEXTURE_MANY_LIGHTS,
60     DM_UNBLENDED_MOD_TEXTURE_AND_DETAIL,
61     DM_BLENDED_MOD_TEXTURE,
62     DM_ALL_DETAILS,
63     DM_BLENDED_DETAILS,
64     DM_SHADOW,
65     DM_SHINY,
66     DM_MASKED_SHINY,
67     DM_ALL_SHINY
68 };
69 
70 /// Virtual/logical texture unit indices. These map to real GL texture units.
71 enum texunitid_t
72 {
73     TU_PRIMARY = 0,
74     TU_PRIMARY_DETAIL,
75     TU_INTER,
76     TU_INTER_DETAIL,
77     NUM_TEXTURE_UNITS
78 };
79 
80 struct AttributeSpec
81 {
82     enum Semantic
83     {
84         TexCoord0,
85         TexCoord1,
86         ModTexCoord,
87 
88         NUM_SEMANTICS
89     };
90 };
91 typedef std::array<de::dint, MAX_TEX_UNITS> TexUnitMap;
92 
93 /**
94  * A list of drawable GL geometry primitives (buffered) and optional GL attribute/state commands.
95  *
96  * Each list is expected to contain a batch (set) of one or more geometry primitives which have been
97  * pre-prepared for uploading to GL from their backing store (buffer). Primitives should be batched
98  * together in order to minimize the number of GL state changes when drawing geometry.
99  *
100  * Presently @ref DrawLists (class) is responsible for managing the lists and assigning list(s) for
101  * a given primitive (according to the current logic for geometry batching).
102  */
103 class DrawList
104 {
105 public:
106     struct Spec
107     {
108         GeomGroup group;
109         de::GLTextureUnit texunits[NUM_TEXTURE_UNITS];
110 
groupSpec111         Spec(GeomGroup group = UnlitGeom) : group(group)
112         {}
113 
unitSpec114         inline de::GLTextureUnit &unit(int index) {
115             DENG2_ASSERT(index >= 0 && index < NUM_TEXTURE_UNITS);
116             return texunits[index];
117         }
118 
unitSpec119         inline de::GLTextureUnit const &unit(int index) const {
120             DENG2_ASSERT(index >= 0 && index < NUM_TEXTURE_UNITS);
121             return texunits[index];
122         }
123     };
124 
125     typedef QVector<de::duint> Indices;
126 
127     struct PrimitiveParams
128     {
129         de::gl::Primitive type;
130 
131         // GL state and flags.
132         enum Flag {
133             Unlit      = 0,
134             OneLight   = 0x1000,
135             ManyLights = 0x2000
136         };
137         Q_DECLARE_FLAGS(Flags, Flag)
138 
139         de::duint32  flags_blendMode;
140         de::Vector2f texScale;
141         de::Vector2f texOffset;
142         de::Vector2f detailTexScale;
143         de::Vector2f detailTexOffset;
144         DGLuint      modTexture;    ///< GL-name of the modulation texture; otherwise @c 0.
145         de::Vector3f modColor;      ///< Modulation color.
146 
147         PrimitiveParams(de::gl::Primitive type,
148                         de::Vector2f texScale        = de::Vector2f(1, 1),
149                         de::Vector2f texOffset       = de::Vector2f(0, 0),
150                         de::Vector2f detailTexScale  = de::Vector2f(1, 1),
151                         de::Vector2f detailTexOffset = de::Vector2f(0, 0),
152                         Flags        flags           = Unlit,
153                         blendmode_t  blendMode       = BM_NORMAL,
154                         DGLuint      modTexture      = 0,
155                         de::Vector3f modColor        = de::Vector3f());
156     };
157 
158 public:
159     /**
160      * Construct a new draw list.
161      *
162      * @param spec  List specification. A copy is made.
163      */
164     DrawList(Spec const &spec);
165 
166     /**
167      * Write indices for a (buffered) geometry primitive to the list.
168      *
169      * @param buffer           Geometry buffer containing the primitive to write.
170      *                         It is the caller's responsibility to ensure this data
171      *                         remains accessible and valid while this DrawList is used
172      *                         (i.e., until a @ref clear(), rewind() or the
173      *                         list itself is destroyed).
174      * @param primParams       GL primitive parameters.
175      * @param indices          Indices for the vertex elements in @a buffer. A copy is made.
176      */
177     DrawList &write(Store const &buffer,
178                     de::duint const *indices, int indexCount,
179                     PrimitiveParams const &primParms);
180 
181     DrawList &write(Store const &buffer,
182                     de::duint const *indices, int indexCount,
183                     de::gl::Primitive primitiveType); // using default parameters
184 
185     DrawList &write(Store const &buffer,
186                     Indices const &indices,
187                     PrimitiveParams const &primParms);
188 
189     DrawList &write(Store const &buffer,
190                     Indices const &indices,
191                     de::gl::Primitive primitiveType); // using default parameters
192 
193     void draw(DrawMode mode, TexUnitMap const &texUnitMap) const;
194 
195     /**
196      * Returns @c true iff there are no commands/geometries in the list.
197      */
198     bool isEmpty() const;
199 
200     /**
201      * Clear the list of all buffered GL commands, returning it to the default, empty state.
202      */
203     void clear();
204 
205     /**
206      * Return the read/write cursor to the beginning of the list, retaining all allocated
207      * storage for buffered GL commands so that it can be reused.
208      *
209      * To be called at the beginning of a new render frame before any geometry is written
210      * to the list.
211      */
212     void rewind();
213 
214     /**
215      * Provides mutable access to the list's specification. Note that any changes to this
216      * configuration will affect @em all geometry in the list.
217      */
218     Spec &spec();
219 
220     /**
221      * Provides immutable access to the list's specification.
222      */
223     Spec const &spec() const;
224 
225 public:
226     static void reserveSpace(Indices &idx, uint count);
227 
228 private:
229     DENG2_PRIVATE(d)
230 };
231 
232 typedef DrawList::Spec DrawListSpec;
233 
234 Q_DECLARE_OPERATORS_FOR_FLAGS(DrawList::PrimitiveParams::Flags)
235 
236 #endif  // CLIENT_RENDER_DRAWLIST_H
237