Line data Source code
1 : /* Copyright (C) 2023 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 : #include "precompiled.h"
19 :
20 : #include "renderer/HWLightingModelRenderer.h"
21 :
22 : #include "graphics/Color.h"
23 : #include "graphics/LightEnv.h"
24 : #include "graphics/Model.h"
25 : #include "graphics/ModelDef.h"
26 : #include "graphics/ShaderProgram.h"
27 : #include "lib/bits.h"
28 : #include "lib/sysdep/rtl.h"
29 : #include "maths/Vector3D.h"
30 : #include "ps/containers/StaticVector.h"
31 : #include "renderer/Renderer.h"
32 : #include "renderer/RenderModifiers.h"
33 : #include "renderer/VertexArray.h"
34 :
35 : namespace
36 : {
37 :
38 : constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_STRIDE = 32;
39 : constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET = 16;
40 : constexpr uint32_t MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET = 0;
41 :
42 : } // anonymous namespace
43 :
44 0 : struct ShaderModelDef : public CModelDefRPrivate
45 : {
46 : /// Indices are the same for all models, so share them
47 : VertexIndexArray m_IndexArray;
48 :
49 : /// Static per-CModelDef vertex array
50 : VertexArray m_Array;
51 :
52 : /// The number of UVs is determined by the model
53 : std::vector<VertexArray::Attribute> m_UVs;
54 :
55 : Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
56 :
57 : ShaderModelDef(const CModelDefPtr& mdef);
58 : };
59 :
60 :
61 0 : ShaderModelDef::ShaderModelDef(const CModelDefPtr& mdef)
62 : : m_IndexArray(false),
63 0 : m_Array(Renderer::Backend::IBuffer::Type::VERTEX, false)
64 : {
65 0 : size_t numVertices = mdef->GetNumVertices();
66 :
67 0 : m_UVs.resize(mdef->GetNumUVsPerVertex());
68 0 : for (size_t i = 0; i < mdef->GetNumUVsPerVertex(); ++i)
69 : {
70 0 : m_UVs[i].format = Renderer::Backend::Format::R32G32_SFLOAT;
71 0 : m_Array.AddAttribute(&m_UVs[i]);
72 : }
73 :
74 0 : m_Array.SetNumberOfVertices(numVertices);
75 0 : m_Array.Layout();
76 :
77 0 : for (size_t i = 0; i < mdef->GetNumUVsPerVertex(); ++i)
78 : {
79 0 : VertexArrayIterator<float[2]> UVit = m_UVs[i].GetIterator<float[2]>();
80 0 : ModelRenderer::BuildUV(mdef, UVit, i);
81 : }
82 :
83 0 : m_Array.Upload();
84 0 : m_Array.FreeBackingStore();
85 :
86 0 : m_IndexArray.SetNumberOfVertices(mdef->GetNumFaces()*3);
87 0 : m_IndexArray.Layout();
88 0 : ModelRenderer::BuildIndices(mdef, m_IndexArray.GetIterator());
89 0 : m_IndexArray.Upload();
90 0 : m_IndexArray.FreeBackingStore();
91 :
92 0 : const uint32_t stride = m_Array.GetStride();
93 : PS::StaticVector<Renderer::Backend::SVertexAttributeFormat, 4> attributes{
94 : {Renderer::Backend::VertexAttributeStream::UV0,
95 0 : m_UVs[0].format, m_UVs[0].offset, stride,
96 : Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0},
97 : {Renderer::Backend::VertexAttributeStream::POSITION,
98 : Renderer::Backend::Format::R32G32B32_SFLOAT,
99 : MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET, MODEL_VERTEX_ATTRIBUTE_STRIDE,
100 : Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1},
101 : {Renderer::Backend::VertexAttributeStream::NORMAL,
102 : Renderer::Backend::Format::R32G32B32_SFLOAT,
103 : MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET, MODEL_VERTEX_ATTRIBUTE_STRIDE,
104 : Renderer::Backend::VertexAttributeRate::PER_VERTEX, 1}
105 0 : };
106 :
107 0 : if (mdef->GetNumUVsPerVertex() >= 2)
108 : {
109 0 : attributes.push_back({
110 : Renderer::Backend::VertexAttributeStream::UV1,
111 0 : m_UVs[1].format, m_UVs[1].offset, stride,
112 : Renderer::Backend::VertexAttributeRate::PER_VERTEX, 0});
113 : }
114 :
115 0 : m_VertexInputLayout = g_Renderer.GetVertexInputLayout({attributes.begin(), attributes.end()});
116 0 : }
117 :
118 :
119 0 : struct ShaderModel : public CModelRData
120 : {
121 : /// Dynamic per-CModel vertex array
122 : VertexArray m_Array;
123 :
124 : /// Position and normals/lighting are recalculated on CPU every frame
125 : VertexArray::Attribute m_Position;
126 : VertexArray::Attribute m_Normal;
127 :
128 0 : ShaderModel(const void* key)
129 0 : : CModelRData(key),
130 0 : m_Array(Renderer::Backend::IBuffer::Type::VERTEX, true)
131 0 : {}
132 : };
133 :
134 :
135 : struct ShaderModelVertexRenderer::ShaderModelRendererInternals
136 : {
137 : /// Previously prepared modeldef
138 : ShaderModelDef* shadermodeldef;
139 : };
140 :
141 :
142 : // Construction and Destruction
143 0 : ShaderModelVertexRenderer::ShaderModelVertexRenderer()
144 : {
145 0 : m = new ShaderModelRendererInternals;
146 0 : m->shadermodeldef = nullptr;
147 0 : }
148 :
149 0 : ShaderModelVertexRenderer::~ShaderModelVertexRenderer()
150 : {
151 0 : delete m;
152 0 : }
153 :
154 :
155 : // Build model data (and modeldef data if necessary)
156 0 : CModelRData* ShaderModelVertexRenderer::CreateModelData(const void* key, CModel* model)
157 : {
158 0 : CModelDefPtr mdef = model->GetModelDef();
159 0 : ShaderModelDef* shadermodeldef = (ShaderModelDef*)mdef->GetRenderData(m);
160 :
161 0 : if (!shadermodeldef)
162 : {
163 0 : shadermodeldef = new ShaderModelDef(mdef);
164 0 : mdef->SetRenderData(m, shadermodeldef);
165 : }
166 :
167 : // Build the per-model data
168 0 : ShaderModel* shadermodel = new ShaderModel(key);
169 :
170 : // Positions and normals must be 16-byte aligned for SSE writes.
171 :
172 0 : shadermodel->m_Position.format = Renderer::Backend::Format::R32G32B32A32_SFLOAT;
173 0 : shadermodel->m_Array.AddAttribute(&shadermodel->m_Position);
174 :
175 0 : shadermodel->m_Normal.format = Renderer::Backend::Format::R32G32B32A32_SFLOAT;
176 0 : shadermodel->m_Array.AddAttribute(&shadermodel->m_Normal);
177 :
178 0 : shadermodel->m_Array.SetNumberOfVertices(mdef->GetNumVertices());
179 0 : shadermodel->m_Array.Layout();
180 :
181 : // Verify alignment
182 0 : ENSURE(shadermodel->m_Position.offset % 16 == 0);
183 0 : ENSURE(shadermodel->m_Normal.offset % 16 == 0);
184 0 : ENSURE(shadermodel->m_Array.GetStride() % 16 == 0);
185 :
186 : // We assume that the vertex input layout is the same for all models with the
187 : // same ShaderModelDef.
188 : // TODO: we need a more strict way to guarantee that.
189 0 : ENSURE(shadermodel->m_Array.GetStride() == MODEL_VERTEX_ATTRIBUTE_STRIDE);
190 0 : ENSURE(shadermodel->m_Position.offset == MODEL_VERTEX_ATTRIBUTE_POSITION_OFFSET);
191 0 : ENSURE(shadermodel->m_Normal.offset == MODEL_VERTEX_ATTRIBUTE_NORMAL_OFFSET);
192 :
193 0 : return shadermodel;
194 : }
195 :
196 :
197 : // Fill in and upload dynamic vertex array
198 0 : void ShaderModelVertexRenderer::UpdateModelData(CModel* model, CModelRData* data, int updateflags)
199 : {
200 0 : ShaderModel* shadermodel = static_cast<ShaderModel*>(data);
201 :
202 0 : if (updateflags & RENDERDATA_UPDATE_VERTICES)
203 : {
204 : // build vertices
205 0 : VertexArrayIterator<CVector3D> Position = shadermodel->m_Position.GetIterator<CVector3D>();
206 0 : VertexArrayIterator<CVector3D> Normal = shadermodel->m_Normal.GetIterator<CVector3D>();
207 :
208 0 : ModelRenderer::BuildPositionAndNormals(model, Position, Normal);
209 :
210 : // upload everything to vertex buffer
211 0 : shadermodel->m_Array.Upload();
212 : }
213 :
214 0 : shadermodel->m_Array.PrepareForRendering();
215 0 : }
216 :
217 0 : void ShaderModelVertexRenderer::UploadModelData(
218 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
219 : CModel* model, CModelRData* data)
220 : {
221 0 : ShaderModelDef* shaderModelDef = static_cast<ShaderModelDef*>(model->GetModelDef()->GetRenderData(m));
222 0 : ENSURE(shaderModelDef);
223 :
224 0 : shaderModelDef->m_Array.UploadIfNeeded(deviceCommandContext);
225 0 : shaderModelDef->m_IndexArray.UploadIfNeeded(deviceCommandContext);
226 :
227 0 : ShaderModel* shaderModel = static_cast<ShaderModel*>(data);
228 :
229 0 : shaderModel->m_Array.UploadIfNeeded(deviceCommandContext);
230 0 : }
231 :
232 : // Prepare UV coordinates for this modeldef
233 0 : void ShaderModelVertexRenderer::PrepareModelDef(
234 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
235 : const CModelDef& def)
236 : {
237 0 : m->shadermodeldef = (ShaderModelDef*)def.GetRenderData(m);
238 :
239 0 : ENSURE(m->shadermodeldef);
240 :
241 0 : deviceCommandContext->SetVertexInputLayout(m->shadermodeldef->m_VertexInputLayout);
242 :
243 0 : const uint32_t stride = m->shadermodeldef->m_Array.GetStride();
244 0 : const uint32_t firstVertexOffset = m->shadermodeldef->m_Array.GetOffset() * stride;
245 :
246 0 : deviceCommandContext->SetVertexBuffer(
247 0 : 0, m->shadermodeldef->m_Array.GetBuffer(), firstVertexOffset);
248 0 : }
249 :
250 : // Render one model
251 0 : void ShaderModelVertexRenderer::RenderModel(
252 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
253 : Renderer::Backend::IShaderProgram* UNUSED(shader), CModel* model, CModelRData* data)
254 : {
255 0 : const CModelDefPtr& mdldef = model->GetModelDef();
256 0 : ShaderModel* shadermodel = static_cast<ShaderModel*>(data);
257 :
258 0 : const uint32_t stride = shadermodel->m_Array.GetStride();
259 0 : const uint32_t firstVertexOffset = shadermodel->m_Array.GetOffset() * stride;
260 :
261 0 : deviceCommandContext->SetVertexBuffer(
262 0 : 1, shadermodel->m_Array.GetBuffer(), firstVertexOffset);
263 0 : deviceCommandContext->SetIndexBuffer(m->shadermodeldef->m_IndexArray.GetBuffer());
264 :
265 : // Render the lot.
266 0 : const size_t numberOfFaces = mdldef->GetNumFaces();
267 :
268 0 : deviceCommandContext->DrawIndexedInRange(
269 0 : m->shadermodeldef->m_IndexArray.GetOffset(), numberOfFaces * 3, 0, mdldef->GetNumVertices() - 1);
270 :
271 : // Bump stats.
272 0 : g_Renderer.m_Stats.m_DrawCalls++;
273 0 : g_Renderer.m_Stats.m_ModelTris += numberOfFaces;
274 3 : }
275 :
|