Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : /*
19 : * Home to the ModelRenderer class, an abstract base class that manages
20 : * a per-frame list of submitted models, as well as simple helper
21 : * classes.
22 : */
23 :
24 : #ifndef INCLUDED_MODELRENDERER
25 : #define INCLUDED_MODELRENDERER
26 :
27 : #include <memory>
28 :
29 : #include "graphics/MeshManager.h"
30 : #include "graphics/RenderableObject.h"
31 : #include "graphics/SColor.h"
32 : #include "renderer/backend/IDeviceCommandContext.h"
33 : #include "renderer/VertexArray.h"
34 :
35 : class RenderModifier;
36 : typedef std::shared_ptr<RenderModifier> RenderModifierPtr;
37 :
38 : class LitRenderModifier;
39 : typedef std::shared_ptr<LitRenderModifier> LitRenderModifierPtr;
40 :
41 : class ModelVertexRenderer;
42 : typedef std::shared_ptr<ModelVertexRenderer> ModelVertexRendererPtr;
43 :
44 : class ModelRenderer;
45 : typedef std::shared_ptr<ModelRenderer> ModelRendererPtr;
46 :
47 : class CModel;
48 : class CShaderDefines;
49 :
50 : /**
51 : * Class CModelRData: Render data that is maintained per CModel.
52 : * ModelRenderer implementations may derive from this class to store
53 : * per-CModel data.
54 : *
55 : * The main purpose of this class over CRenderData is to track which
56 : * ModelRenderer the render data belongs to (via the key that is passed
57 : * to the constructor). When a model changes the renderer it uses
58 : * (e.g. via run-time modification of the renderpath configuration),
59 : * the old ModelRenderer's render data is supposed to be replaced by
60 : * the new data.
61 : */
62 0 : class CModelRData : public CRenderData
63 : {
64 : public:
65 0 : CModelRData(const void* key) : m_Key(key) { }
66 :
67 : /**
68 : * GetKey: Retrieve the key that can be used to identify the
69 : * ModelRenderer that created this data.
70 : *
71 : * @return The opaque key that was passed to the constructor.
72 : */
73 0 : const void* GetKey() const { return m_Key; }
74 :
75 : private:
76 : /// The key for model renderer identification
77 : const void* m_Key;
78 : };
79 :
80 :
81 : /**
82 : * Class ModelRenderer: Abstract base class for all model renders.
83 : *
84 : * A ModelRenderer manages a per-frame list of models.
85 : *
86 : * It is supposed to be derived in order to create new ways in which
87 : * the per-frame list of models can be managed (for batching, for
88 : * transparent rendering, etc.) or potentially for rarely used special
89 : * effects.
90 : *
91 : * A typical ModelRenderer will delegate vertex transformation/setup
92 : * to a ModelVertexRenderer.
93 : * It will delegate fragment stage setup to a RenderModifier.
94 : *
95 : * For most purposes, you should use a BatchModelRenderer with
96 : * specialized ModelVertexRenderer and RenderModifier implementations.
97 : *
98 : * It is suggested that a derived class implement the provided generic
99 : * Render function, however in some cases it may be necessary to supply
100 : * a Render function with a different prototype.
101 : *
102 : * ModelRenderer also contains a number of static helper functions
103 : * for building vertex arrays.
104 : */
105 : class ModelRenderer
106 : {
107 : public:
108 0 : ModelRenderer() { }
109 0 : virtual ~ModelRenderer() { }
110 :
111 : /**
112 : * Initialise global settings.
113 : * Should be called before using the class.
114 : */
115 : static void Init();
116 :
117 : /**
118 : * Submit: Submit a model for rendering this frame.
119 : *
120 : * preconditions : The model must not have been submitted to any
121 : * ModelRenderer in this frame. Submit may only be called
122 : * after EndFrame and before PrepareModels.
123 : *
124 : * @param model The model that will be added to the list of models
125 : * submitted this frame.
126 : */
127 : virtual void Submit(int cullGroup, CModel* model) = 0;
128 :
129 : /**
130 : * PrepareModels: Calculate renderer data for all previously
131 : * submitted models.
132 : *
133 : * Must be called before any rendering calls and after all models
134 : * for this frame have been submitted.
135 : */
136 : virtual void PrepareModels() = 0;
137 :
138 : /**
139 : * Upload renderer data for all previously submitted models to backend.
140 : *
141 : * Must be called before any rendering calls and after all models
142 : * for this frame have been prepared.
143 : */
144 : virtual void UploadModels(
145 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext) = 0;
146 :
147 : /**
148 : * EndFrame: Remove all models from the list of submitted
149 : * models.
150 : */
151 : virtual void EndFrame() = 0;
152 :
153 : /**
154 : * Render: Render submitted models, using the given RenderModifier to setup
155 : * the fragment stage.
156 : *
157 : * @note It is suggested that derived model renderers implement and use
158 : * this Render functions. However, a highly specialized model renderer
159 : * may need to "disable" this function and provide its own Render function
160 : * with a different prototype.
161 : *
162 : * preconditions : PrepareModels must be called after all models have been
163 : * submitted and before calling Render.
164 : *
165 : * @param modifier The RenderModifier that specifies the fragment stage.
166 : * @param flags If flags is 0, all submitted models are rendered.
167 : * If flags is non-zero, only models that contain flags in their
168 : * CModel::GetFlags() are rendered.
169 : */
170 : virtual void Render(
171 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
172 : const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags) = 0;
173 :
174 : /**
175 : * CopyPositionAndNormals: Copy unanimated object-space vertices and
176 : * normals into the given vertex array.
177 : *
178 : * @param mdef The underlying CModelDef that contains mesh data.
179 : * @param Position Points to the array that will receive
180 : * position vectors. The array behind the iterator
181 : * must be large enough to hold model->GetModelDef()->GetNumVertices()
182 : * vertices.
183 : * @param Normal Points to the array that will receive normal vectors.
184 : * The array behind the iterator must be as large as the Position array.
185 : */
186 : static void CopyPositionAndNormals(
187 : const CModelDefPtr& mdef,
188 : const VertexArrayIterator<CVector3D>& Position,
189 : const VertexArrayIterator<CVector3D>& Normal);
190 :
191 : /**
192 : * BuildPositionAndNormals: Build animated vertices and normals,
193 : * transformed into world space.
194 : *
195 : * @param model The model that is to be transformed.
196 : * @param Position Points to the array that will receive
197 : * transformed position vectors. The array behind the iterator
198 : * must be large enough to hold model->GetModelDef()->GetNumVertices()
199 : * vertices. It must allow 16 bytes to be written to each element
200 : * (i.e. provide 4 bytes of padding after each CVector3D).
201 : * @param Normal Points to the array that will receive transformed
202 : * normal vectors. The array behind the iterator must be as large as
203 : * the Position array.
204 : */
205 : static void BuildPositionAndNormals(
206 : CModel* model,
207 : const VertexArrayIterator<CVector3D>& Position,
208 : const VertexArrayIterator<CVector3D>& Normal);
209 :
210 : /**
211 : * BuildColor4ub: Build lighting colors for the given model,
212 : * based on previously calculated world space normals.
213 : *
214 : * @param model The model that is to be lit.
215 : * @param Normal Array of the model's normal vectors, animated and
216 : * transformed into world space.
217 : * @param Color Points to the array that will receive the lit vertex color.
218 : * The array behind the iterator must large enough to hold
219 : * model->GetModelDef()->GetNumVertices() vertices.
220 : */
221 : static void BuildColor4ub(
222 : CModel* model,
223 : const VertexArrayIterator<CVector3D>& Normal,
224 : const VertexArrayIterator<SColor4ub>& Color);
225 :
226 : /**
227 : * BuildUV: Copy UV coordinates into the given vertex array.
228 : *
229 : * @param mdef The model def.
230 : * @param UV Points to the array that will receive UV coordinates.
231 : * The array behind the iterator must large enough to hold
232 : * mdef->GetNumVertices() vertices.
233 : */
234 : static void BuildUV(
235 : const CModelDefPtr& mdef,
236 : const VertexArrayIterator<float[2]>& UV,
237 : int UVset);
238 :
239 : /**
240 : * BuildIndices: Create the indices array for the given CModelDef.
241 : *
242 : * @param mdef The model definition object.
243 : * @param Indices The index array, must be able to hold
244 : * mdef->GetNumFaces()*3 elements.
245 : */
246 : static void BuildIndices(
247 : const CModelDefPtr& mdef,
248 : const VertexArrayIterator<u16>& Indices);
249 :
250 : /**
251 : * GenTangents: Generate tangents for the given CModelDef.
252 : *
253 : * @param mdef The model definition object.
254 : * @param newVertices An out vector of the unindexed vertices with tangents added.
255 : * The new vertices cannot be used with existing face index and must be welded/reindexed.
256 : */
257 : static void GenTangents(const CModelDefPtr& mdef, std::vector<float>& newVertices, bool gpuSkinning);
258 : };
259 :
260 : /**
261 : * Implementation of ModelRenderer that loads the appropriate shaders for
262 : * rendering each model, and that batches by shader technique (and by mesh and texture).
263 : */
264 : class ShaderModelRenderer : public ModelRenderer
265 : {
266 : friend struct ShaderModelRendererInternals;
267 :
268 : public:
269 : ShaderModelRenderer(ModelVertexRendererPtr vertexrender);
270 : ~ShaderModelRenderer() override;
271 :
272 : // Batching implementations
273 : void Submit(int cullGroup, CModel* model) override;
274 : void PrepareModels() override;
275 : void UploadModels(
276 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext) override;
277 : void EndFrame() override;
278 : void Render(
279 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
280 : const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags) override;
281 :
282 : private:
283 : struct ShaderModelRendererInternals;
284 : ShaderModelRendererInternals* m;
285 : };
286 :
287 : #endif // INCLUDED_MODELRENDERER
|