Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DecalRData.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 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 "DecalRData.h"
21 
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"
28 #include "ps/CLogger.h"
29 #include "ps/Game.h"
30 #include "ps/Profile.h"
31 #include "renderer/Renderer.h"
35 
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.
40 
42  : m_Decal(decal), m_IndexArray(GL_STATIC_DRAW), m_Array(GL_STATIC_DRAW), m_Simulation(simulation)
43 {
44  m_Position.type = GL_FLOAT;
45  m_Position.elems = 3;
47 
48  m_DiffuseColor.type = GL_UNSIGNED_BYTE;
51 
52  m_UV.type = GL_FLOAT;
53  m_UV.elems = 2;
55 
56  BuildArrays();
57 }
58 
60 {
61 }
62 
64 {
65  m_Simulation = simulation;
66  if (m_UpdateFlags != 0)
67  {
68  BuildArrays();
69  m_UpdateFlags = 0;
70  }
71 }
72 
73 void CDecalRData::RenderDecals(std::vector<CDecalRData*>& decals, const CShaderDefines& context,
74  ShadowMap* shadow, bool isDummyShader, const CShaderProgramPtr& dummy)
75 {
76  CShaderDefines contextDecal = context;
77  contextDecal.Add(str_DECAL, str_1);
78 
79  for (size_t i = 0; i < decals.size(); ++i)
80  {
81  CDecalRData *decal = decals[i];
82 
83  CMaterial &material = decal->m_Decal->m_Decal.m_Material;
84 
85  if (material.GetShaderEffect().length() == 0)
86  {
87  LOGERROR(L"Terrain renderer failed to load shader effect.\n");
88  continue;
89  }
90 
91  int numPasses = 1;
92  CShaderTechniquePtr techBase;
93 
94  if (!isDummyShader)
95  {
96  techBase = g_Renderer.GetShaderManager().LoadEffect(
97  material.GetShaderEffect(), contextDecal, material.GetShaderDefines(0));
98 
99  if (!techBase)
100  {
101  LOGERROR(L"Terrain renderer failed to load shader effect (%hs)\n",
102  material.GetShaderEffect().string().c_str());
103  continue;
104  }
105 
106  numPasses = techBase->GetNumPasses();
107  }
108 
109  for (int pass = 0; pass < numPasses; ++pass)
110  {
111  if (!isDummyShader)
112  {
113  techBase->BeginPass(pass);
114  TerrainRenderer::PrepareShader(techBase->GetShader(), shadow);
115 
116  glEnable(GL_BLEND);
117  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
118  }
119 
120  const CShaderProgramPtr& shader = isDummyShader ? dummy : techBase->GetShader(pass);
121 
122  if (material.GetSamplers().size() != 0)
123  {
124  const CMaterial::SamplersVector& samplers = material.GetSamplers();
125  size_t samplersNum = samplers.size();
126 
127  for (size_t s = 0; s < samplersNum; ++s)
128  {
129  const CMaterial::TextureSampler& samp = samplers[s];
130  shader->BindTexture(samp.Name, samp.Sampler);
131  }
132 
133  material.GetStaticUniforms().BindUniforms(shader);
134 
135  // TODO: Need to handle floating decals correctly. In particular, we need
136  // to render non-floating before water and floating after water (to get
137  // the blending right), and we also need to apply the correct lighting in
138  // each case, which doesn't really seem possible with the current
139  // TerrainRenderer.
140  // Also, need to mark the decals as dirty when water height changes.
141 
142  // glDisable(GL_TEXTURE_2D);
143  // m_Decal->GetBounds().Render();
144  // glEnable(GL_TEXTURE_2D);
145 
146  u8* base = decal->m_Array.Bind();
147  GLsizei stride = (GLsizei)decal->m_Array.GetStride();
148 
149  u8* indexBase = decal->m_IndexArray.Bind();
150 
151 #if !CONFIG2_GLES
152  if (isDummyShader)
153  {
154  glColor3fv(decal->m_Decal->GetShadingColor().FloatArray());
155  }
156  else
157 #endif
158  {
159 
160  shader->Uniform(str_shadingColor, decal->m_Decal->GetShadingColor());
161  }
162 
163  shader->VertexPointer(3, GL_FLOAT, stride, base + decal->m_Position.offset);
164  shader->ColorPointer(4, GL_UNSIGNED_BYTE, stride, base + decal->m_DiffuseColor.offset);
165  shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, stride, base + decal->m_UV.offset);
166 
167  shader->AssertPointersBound();
168 
169  if (!g_Renderer.m_SkipSubmit)
170  {
171  glDrawElements(GL_TRIANGLES, (GLsizei)decal->m_IndexArray.GetNumVertices(), GL_UNSIGNED_SHORT, indexBase);
172  }
173 
174  // bump stats
175  g_Renderer.m_Stats.m_DrawCalls++;
176  g_Renderer.m_Stats.m_TerrainTris += decal->m_IndexArray.GetNumVertices() / 3;
177 
179  }
180 
181  if (!isDummyShader)
182  {
183  glDisable(GL_BLEND);
184  techBase->EndPass();
185  }
186  }
187  }
188 }
189 
191 {
192  PROFILE("decal build");
193 
194  const SDecal& decal = m_Decal->m_Decal;
195 
196  // TODO: Currently this constructs an axis-aligned bounding rectangle around
197  // the decal. It would be more efficient for rendering if we excluded tiles
198  // that are outside the (non-axis-aligned) decal rectangle.
199 
200  ssize_t i0, j0, i1, j1;
201  m_Decal->CalcVertexExtents(i0, j0, i1, j1);
202 
203  // Construct vertex data arrays
204 
206 
207  m_Array.SetNumVertices((i1-i0+1)*(j1-j0+1));
208  m_Array.Layout();
212 
213  const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
214  bool cpuLighting = (g_Renderer.GetRenderPath() == CRenderer::RP_FIXED);
215 
216  for (ssize_t j = j0; j <= j1; ++j)
217  {
218  for (ssize_t i = i0; i <= i1; ++i)
219  {
220  CVector3D pos;
221  m_Decal->m_Terrain->CalcPosition(i, j, pos);
222 
223  if (decal.m_Floating && cmpWaterManager)
224  pos.Y = std::max(pos.Y, cmpWaterManager->GetExactWaterLevel(pos.X, pos.Z));
225 
226  *Position = pos;
227  ++Position;
228 
229  CVector3D normal;
230  m_Decal->m_Terrain->CalcNormal(i, j, normal);
231  *DiffuseColor = cpuLighting ? lightEnv.EvaluateTerrainDiffuseScaled(normal) : lightEnv.EvaluateTerrainDiffuseFactor(normal);
232  ++DiffuseColor;
233 
234  // Map from world space back into decal texture space
236  (*UV)[0] = 0.5f + (inv.X - decal.m_OffsetX) / decal.m_SizeX;
237  (*UV)[1] = 0.5f - (inv.Z - decal.m_OffsetZ) / decal.m_SizeZ; // flip V to match our texture convention
238  ++UV;
239  }
240  }
241 
242  m_Array.Upload();
244 
245  // Construct index arrays for each terrain tile
246 
247  m_IndexArray.SetNumVertices((i1-i0)*(j1-j0)*6);
250 
251  u16 base = 0;
252  ssize_t w = i1-i0+1;
253  for (ssize_t dj = 0; dj < j1-j0; ++dj)
254  {
255  for (ssize_t di = 0; di < i1-i0; ++di)
256  {
257  bool dir = m_Decal->m_Terrain->GetTriangulationDir(i0+di, j0+dj);
258  if (dir)
259  {
260  *Index++ = u16(((dj+0)*w+(di+0))+base);
261  *Index++ = u16(((dj+0)*w+(di+1))+base);
262  *Index++ = u16(((dj+1)*w+(di+0))+base);
263 
264  *Index++ = u16(((dj+0)*w+(di+1))+base);
265  *Index++ = u16(((dj+1)*w+(di+1))+base);
266  *Index++ = u16(((dj+1)*w+(di+0))+base);
267  }
268  else
269  {
270  *Index++ = u16(((dj+0)*w+(di+0))+base);
271  *Index++ = u16(((dj+0)*w+(di+1))+base);
272  *Index++ = u16(((dj+1)*w+(di+1))+base);
273 
274  *Index++ = u16(((dj+1)*w+(di+1))+base);
275  *Index++ = u16(((dj+1)*w+(di+0))+base);
276  *Index++ = u16(((dj+0)*w+(di+0))+base);
277  }
278  }
279  }
280 
283 }
void Add(CStrIntern name, CStrIntern value)
Add a name and associated value to the map of defines.
#define u8
Definition: types.h:39
CSimulation2 * m_Simulation
Definition: DecalRData.h:55
bool m_Floating
Definition: Decal.h:47
#define LOGERROR
Definition: CLogger.h:35
CMaterial m_Material
Definition: Decal.h:41
const std::string & string() const
Returns as std::string.
Definition: CStrIntern.cpp:150
const CMatrix3D & GetInvTransform() const
size_t length() const
Returns length of string in bytes.
Definition: CStrIntern.cpp:145
VertexArrayIterator< u16 > GetIterator() const
Gets the iterator over the (only) attribute in this array, i.e. a u16.
VertexArray::Attribute m_UV
Definition: DecalRData.h:51
float m_SizeZ
Definition: Decal.h:43
void CalcPosition(ssize_t i, ssize_t j, CVector3D &pos) const
Definition: Terrain.cpp:118
CVector3D Transform(const CVector3D &vector) const
Definition: Matrix3D.h:272
bool GetTriangulationDir(ssize_t i, ssize_t j) const
Definition: Terrain.cpp:427
void AddAttribute(Attribute *attr)
Definition: VertexArray.cpp:75
shared_ptr< CShaderTechnique > CShaderTechniquePtr
VertexArray::Attribute m_Position
Definition: DecalRData.h:49
void FreeBackingStore()
Class ShadowMap: Maintain the shadow map texture and perform necessary OpenGL setup, including matrix calculations.
Definition: ShadowMap.h:39
VertexArray::Attribute m_DiffuseColor
Definition: DecalRData.h:50
CDecalRData(CModelDecal *decal, CSimulation2 *simulation)
Definition: DecalRData.cpp:41
float m_OffsetX
Definition: Decal.h:45
const entity_id_t SYSTEM_ENTITY
Entity ID for singleton &#39;system&#39; components.
Definition: Entity.h:44
Public API for simulation system.
Definition: Simulation2.h:46
SDecal m_Decal
Definition: Decal.h:89
#define g_Renderer
Definition: Renderer.h:61
void Update(CSimulation2 *simulation)
Definition: DecalRData.cpp:63
void CalcNormal(ssize_t i, ssize_t j, CVector3D &normal) const
Definition: Terrain.cpp:144
VertexArray m_Array
Definition: DecalRData.h:48
CModelDecal * m_Decal
Definition: DecalRData.h:53
void BindUniforms(const CShaderProgramPtr &shader) const
Bind the collection of uniforms onto the given shader.
float X
Definition: Vector3D.h:31
float Y
Definition: Vector3D.h:31
virtual float GetExactWaterLevel(float x, float z)=0
Get the current water level at the given point.
void CalcVertexExtents(ssize_t &i0, ssize_t &j0, ssize_t &i1, ssize_t &j1)
Compute the terrain vertex indexes that bound the decal&#39;s projection onto the terrain.
Definition: Decal.cpp:31
void SetNumVertices(size_t num)
Definition: VertexArray.cpp:64
#define PROFILE(name)
Definition: Profile.h:195
Terrain decal definition.
Definition: Decal.h:32
VertexIndexArray m_IndexArray
Definition: DecalRData.h:46
A simplified syntax for accessing entity components.
Definition: CmpPtr.h:55
VertexArrayIterator< T > GetIterator() const
intptr_t ssize_t
Definition: wposix_types.h:82
Represents a mapping of name strings to value strings, for use with #if and #ifdef and similar condit...
void BuildArrays()
Definition: DecalRData.cpp:190
#define u16
Definition: types.h:40
static void PrepareShader(const CShaderProgramPtr &shader, ShadowMap *shadow)
Set up all the uniforms for a shader pass.
const SamplersVector & GetSamplers() const
Definition: Material.h:72
float m_SizeX
Definition: Decal.h:42
const CShaderUniforms & GetStaticUniforms() const
Definition: Material.h:69
const float * FloatArray() const
Definition: Overlay.h:49
std::vector< TextureSampler > SamplersVector
Definition: Material.h:40
float Z
Definition: Vector3D.h:31
const CShaderDefines & GetShaderDefines(uint32_t conditionFlags) const
Definition: Material.h:61
virtual CColor GetShadingColor() const
CTerrain * m_Terrain
Definition: Decal.h:88
static void Unbind()
Unbind any currently-bound buffer, so glVertexPointer etc calls will not attempt to use it...
Class CLightEnv: description of a lighting environment - contains all the necessary parameters for re...
Definition: LightEnv.h:36
CStrIntern GetShaderEffect() const
Definition: Material.h:53
static void RenderDecals(std::vector< CDecalRData * > &decals, const CShaderDefines &context, ShadowMap *shadow, bool isDummyShader=false, const CShaderProgramPtr &dummy=CShaderProgramPtr())
Definition: DecalRData.cpp:73
float m_OffsetZ
Definition: Decal.h:46
shared_ptr< CShaderProgram > CShaderProgramPtr
size_t GetStride() const
Definition: VertexArray.h:169
size_t GetNumVertices() const
Definition: VertexArray.h:168