Add the ceasefire settings to the new simulation settings system.
[0ad.git] / source / renderer / DecalRData.cpp
blob9dec8f0d07d7785e1eaf0fd1270bea7a2ee183bc
1 /* Copyright (C) 2015 Wildfire Games.
2 * This file is part of 0 A.D.
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.
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.
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/>.
18 #include "precompiled.h"
20 #include "DecalRData.h"
22 #include "graphics/Decal.h"
23 #include "graphics/LightEnv.h"
24 #include "graphics/Model.h"
25 #include "graphics/ShaderManager.h"
26 #include "graphics/Terrain.h"
27 #include "graphics/TextureManager.h"
28 #include "ps/CLogger.h"
29 #include "ps/Game.h"
30 #include "ps/Profile.h"
31 #include "renderer/Renderer.h"
32 #include "renderer/TerrainRenderer.h"
33 #include "simulation2/Simulation2.h"
34 #include "simulation2/components/ICmpWaterManager.h"
36 // TODO: Currently each decal is a separate CDecalRData. We might want to use
37 // lots of decals for special effects like shadows, footprints, etc, in which
38 // case we should probably redesign this to batch them all together for more
39 // efficient rendering.
41 CDecalRData::CDecalRData(CModelDecal* decal, CSimulation2* simulation)
42 : m_Decal(decal), m_IndexArray(GL_STATIC_DRAW), m_Array(GL_STATIC_DRAW), m_Simulation(simulation)
44 m_Position.type = GL_FLOAT;
45 m_Position.elems = 3;
46 m_Array.AddAttribute(&m_Position);
48 m_Normal.type = GL_FLOAT;
49 m_Normal.elems = 3;
50 m_Array.AddAttribute(&m_Normal);
52 m_DiffuseColor.type = GL_UNSIGNED_BYTE;
53 m_DiffuseColor.elems = 4;
54 m_Array.AddAttribute(&m_DiffuseColor);
56 m_UV.type = GL_FLOAT;
57 m_UV.elems = 2;
58 m_Array.AddAttribute(&m_UV);
60 BuildArrays();
63 CDecalRData::~CDecalRData()
67 void CDecalRData::Update(CSimulation2* simulation)
69 m_Simulation = simulation;
70 if (m_UpdateFlags != 0)
72 BuildArrays();
73 m_UpdateFlags = 0;
77 void CDecalRData::RenderDecals(std::vector<CDecalRData*>& decals, const CShaderDefines& context,
78 ShadowMap* shadow, bool isDummyShader, const CShaderProgramPtr& dummy)
80 CShaderDefines contextDecal = context;
81 contextDecal.Add(str_DECAL, str_1);
83 for (size_t i = 0; i < decals.size(); ++i)
85 CDecalRData *decal = decals[i];
87 CMaterial &material = decal->m_Decal->m_Decal.m_Material;
89 if (material.GetShaderEffect().length() == 0)
91 LOGERROR("Terrain renderer failed to load shader effect.\n");
92 continue;
95 int numPasses = 1;
96 CShaderTechniquePtr techBase;
98 if (!isDummyShader)
100 techBase = g_Renderer.GetShaderManager().LoadEffect(
101 material.GetShaderEffect(), contextDecal, material.GetShaderDefines(0));
103 if (!techBase)
105 LOGERROR("Terrain renderer failed to load shader effect (%s)\n",
106 material.GetShaderEffect().string().c_str());
107 continue;
110 numPasses = techBase->GetNumPasses();
113 for (int pass = 0; pass < numPasses; ++pass)
115 if (!isDummyShader)
117 techBase->BeginPass(pass);
118 TerrainRenderer::PrepareShader(techBase->GetShader(), shadow);
120 glEnable(GL_BLEND);
121 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
124 const CShaderProgramPtr& shader = isDummyShader ? dummy : techBase->GetShader(pass);
126 if (material.GetSamplers().size() != 0)
128 const CMaterial::SamplersVector& samplers = material.GetSamplers();
129 size_t samplersNum = samplers.size();
131 for (size_t s = 0; s < samplersNum; ++s)
133 const CMaterial::TextureSampler& samp = samplers[s];
134 shader->BindTexture(samp.Name, samp.Sampler);
137 material.GetStaticUniforms().BindUniforms(shader);
139 // TODO: Need to handle floating decals correctly. In particular, we need
140 // to render non-floating before water and floating after water (to get
141 // the blending right), and we also need to apply the correct lighting in
142 // each case, which doesn't really seem possible with the current
143 // TerrainRenderer.
144 // Also, need to mark the decals as dirty when water height changes.
146 // glDisable(GL_TEXTURE_2D);
147 // m_Decal->GetBounds().Render();
148 // glEnable(GL_TEXTURE_2D);
150 u8* base = decal->m_Array.Bind();
151 GLsizei stride = (GLsizei)decal->m_Array.GetStride();
153 u8* indexBase = decal->m_IndexArray.Bind();
155 #if !CONFIG2_GLES
156 if (isDummyShader)
158 glColor3fv(decal->m_Decal->GetShadingColor().FloatArray());
160 else
161 #endif
164 shader->Uniform(str_shadingColor, decal->m_Decal->GetShadingColor());
167 shader->VertexPointer(3, GL_FLOAT, stride, base + decal->m_Position.offset);
168 shader->NormalPointer(GL_FLOAT, stride, base + decal->m_Normal.offset);
169 shader->ColorPointer(4, GL_UNSIGNED_BYTE, stride, base + decal->m_DiffuseColor.offset);
170 shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, stride, base + decal->m_UV.offset);
172 shader->AssertPointersBound();
174 if (!g_Renderer.m_SkipSubmit)
176 glDrawElements(GL_TRIANGLES, (GLsizei)decal->m_IndexArray.GetNumVertices(), GL_UNSIGNED_SHORT, indexBase);
179 // bump stats
180 g_Renderer.m_Stats.m_DrawCalls++;
181 g_Renderer.m_Stats.m_TerrainTris += decal->m_IndexArray.GetNumVertices() / 3;
183 CVertexBuffer::Unbind();
186 if (!isDummyShader)
188 glDisable(GL_BLEND);
189 techBase->EndPass();
195 void CDecalRData::BuildArrays()
197 PROFILE("decal build");
199 const SDecal& decal = m_Decal->m_Decal;
201 // TODO: Currently this constructs an axis-aligned bounding rectangle around
202 // the decal. It would be more efficient for rendering if we excluded tiles
203 // that are outside the (non-axis-aligned) decal rectangle.
205 ssize_t i0, j0, i1, j1;
206 m_Decal->CalcVertexExtents(i0, j0, i1, j1);
208 // Construct vertex data arrays
210 CmpPtr<ICmpWaterManager> cmpWaterManager(*m_Simulation, SYSTEM_ENTITY);
212 m_Array.SetNumVertices((i1-i0+1)*(j1-j0+1));
213 m_Array.Layout();
214 VertexArrayIterator<CVector3D> Position = m_Position.GetIterator<CVector3D>();
215 VertexArrayIterator<CVector3D> Normal = m_Normal.GetIterator<CVector3D>();
216 VertexArrayIterator<SColor4ub> DiffuseColor = m_DiffuseColor.GetIterator<SColor4ub>();
217 VertexArrayIterator<float[2]> UV = m_UV.GetIterator<float[2]>();
219 const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
220 bool cpuLighting = (g_Renderer.GetRenderPath() == CRenderer::RP_FIXED);
222 for (ssize_t j = j0; j <= j1; ++j)
224 for (ssize_t i = i0; i <= i1; ++i)
226 CVector3D pos;
227 m_Decal->m_Terrain->CalcPosition(i, j, pos);
229 if (decal.m_Floating && cmpWaterManager)
230 pos.Y = std::max(pos.Y, cmpWaterManager->GetExactWaterLevel(pos.X, pos.Z));
232 *Position = pos;
233 ++Position;
235 CVector3D normal;
236 m_Decal->m_Terrain->CalcNormal(i, j, normal);
237 *Normal = normal;
238 Normal++;
240 *DiffuseColor = cpuLighting ? lightEnv.EvaluateTerrainDiffuseScaled(normal) : lightEnv.EvaluateTerrainDiffuseFactor(normal);
241 ++DiffuseColor;
243 // Map from world space back into decal texture space
244 CVector3D inv = m_Decal->GetInvTransform().Transform(pos);
245 (*UV)[0] = 0.5f + (inv.X - decal.m_OffsetX) / decal.m_SizeX;
246 (*UV)[1] = 0.5f - (inv.Z - decal.m_OffsetZ) / decal.m_SizeZ; // flip V to match our texture convention
247 ++UV;
251 m_Array.Upload();
252 m_Array.FreeBackingStore();
254 // Construct index arrays for each terrain tile
256 m_IndexArray.SetNumVertices((i1-i0)*(j1-j0)*6);
257 m_IndexArray.Layout();
258 VertexArrayIterator<u16> Index = m_IndexArray.GetIterator();
260 u16 base = 0;
261 ssize_t w = i1-i0+1;
262 for (ssize_t dj = 0; dj < j1-j0; ++dj)
264 for (ssize_t di = 0; di < i1-i0; ++di)
266 bool dir = m_Decal->m_Terrain->GetTriangulationDir(i0+di, j0+dj);
267 if (dir)
269 *Index++ = u16(((dj+0)*w+(di+0))+base);
270 *Index++ = u16(((dj+0)*w+(di+1))+base);
271 *Index++ = u16(((dj+1)*w+(di+0))+base);
273 *Index++ = u16(((dj+0)*w+(di+1))+base);
274 *Index++ = u16(((dj+1)*w+(di+1))+base);
275 *Index++ = u16(((dj+1)*w+(di+0))+base);
277 else
279 *Index++ = u16(((dj+0)*w+(di+0))+base);
280 *Index++ = u16(((dj+0)*w+(di+1))+base);
281 *Index++ = u16(((dj+1)*w+(di+1))+base);
283 *Index++ = u16(((dj+1)*w+(di+1))+base);
284 *Index++ = u16(((dj+1)*w+(di+0))+base);
285 *Index++ = u16(((dj+0)*w+(di+0))+base);
290 m_IndexArray.Upload();
291 m_IndexArray.FreeBackingStore();