Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TerrainRenderer.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2013 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  * Terrain rendering (everything related to patches and water) is
20  * encapsulated in TerrainRenderer
21  */
22 
23 #include "precompiled.h"
24 
25 #include "graphics/Camera.h"
26 #include "graphics/Decal.h"
27 #include "graphics/LightEnv.h"
28 #include "graphics/LOSTexture.h"
29 #include "graphics/Patch.h"
30 #include "graphics/GameView.h"
31 #include "graphics/Model.h"
32 #include "graphics/ShaderManager.h"
33 #include "renderer/ShadowMap.h"
34 #include "renderer/SkyManager.h"
36 #include "graphics/TextRenderer.h"
37 
38 #include "maths/MathUtil.h"
39 
40 #include "ps/Filesystem.h"
41 #include "ps/CLogger.h"
42 #include "ps/Font.h"
43 #include "ps/Game.h"
44 #include "ps/Profile.h"
45 #include "ps/World.h"
46 
47 #include "renderer/DecalRData.h"
48 #include "renderer/PatchRData.h"
49 #include "renderer/Renderer.h"
50 #include "renderer/ShadowMap.h"
52 #include "renderer/VertexArray.h"
53 #include "renderer/WaterManager.h"
54 
55 #include "tools/atlas/GameInterface/GameLoop.h"
56 
57 extern GameLoopState* g_AtlasGameLoop;
58 
59 ///////////////////////////////////////////////////////////////////////////////////////////////
60 // TerrainRenderer implementation
61 
62 
63 /**
64  * TerrainRenderer keeps track of which phase it is in, to detect
65  * when Submit, PrepareForRendering etc. are called in the wrong order.
66  */
67 enum Phase {
70 };
71 
72 
73 /**
74  * Struct TerrainRendererInternals: Internal variables used by the TerrainRenderer class.
75  */
77 {
78  /// Which phase (submitting or rendering patches) are we in right now?
80 
81  /// Patches that were submitted for this frame
82  std::vector<CPatchRData*> visiblePatches;
83  std::vector<CPatchRData*> filteredPatches;
84 
85  /// Decals that were submitted for this frame
86  std::vector<CDecalRData*> visibleDecals;
87  std::vector<CDecalRData*> filteredDecals;
88 
89  /// Fancy water shader
92 
94 };
95 
96 
97 
98 ///////////////////////////////////////////////////////////////////
99 // Construction/Destruction
101 {
102  m = new TerrainRendererInternals();
103  m->phase = Phase_Submit;
104 }
105 
107 {
108  delete m;
109 }
110 
112 {
113  m->simulation = simulation;
114 }
115 
116 ///////////////////////////////////////////////////////////////////
117 // Submit a patch for rendering
119 {
120  ENSURE(m->phase == Phase_Submit);
121 
122  CPatchRData* data = (CPatchRData*)patch->GetRenderData();
123  if (data == 0)
124  {
125  // no renderdata for patch, create it now
126  data = new CPatchRData(patch, m->simulation);
127  patch->SetRenderData(data);
128  }
129  data->Update(m->simulation);
130 
131  m->visiblePatches.push_back(data);
132 }
133 
134 ///////////////////////////////////////////////////////////////////
135 // Submit a decal for rendering
137 {
138  ENSURE(m->phase == Phase_Submit);
139 
140  CDecalRData* data = (CDecalRData*)decal->GetRenderData();
141  if (data == 0)
142  {
143  // no renderdata for decal, create it now
144  data = new CDecalRData(decal, m->simulation);
145  decal->SetRenderData(data);
146  }
147  data->Update(m->simulation);
148 
149  m->visibleDecals.push_back(data);
150 }
151 
152 ///////////////////////////////////////////////////////////////////
153 // Prepare for rendering
155 {
156  ENSURE(m->phase == Phase_Submit);
157 
158  m->phase = Phase_Render;
159 }
160 
161 ///////////////////////////////////////////////////////////////////
162 // Clear submissions lists
164 {
166 
167  m->visiblePatches.clear();
168  m->visibleDecals.clear();
169 
170  m->phase = Phase_Submit;
171 }
172 
173 
174 ///////////////////////////////////////////////////////////////////
175 // Culls patches and decals against a frustum.
177 {
178  m->filteredPatches.clear();
179  for (std::vector<CPatchRData*>::iterator it = m->visiblePatches.begin(); it != m->visiblePatches.end(); ++it)
180  {
181  if (frustum->IsBoxVisible(CVector3D(0, 0, 0), (*it)->GetPatch()->GetWorldBounds()))
182  m->filteredPatches.push_back(*it);
183  }
184 
185  m->filteredDecals.clear();
186  for (std::vector<CDecalRData*>::iterator it = m->visibleDecals.begin(); it != m->visibleDecals.end(); ++it)
187  {
188  if (frustum->IsBoxVisible(CVector3D(0, 0, 0), (*it)->GetDecal()->GetWorldBounds()))
189  m->filteredDecals.push_back(*it);
190  }
191 
192  return !m->filteredPatches.empty() || !m->filteredDecals.empty();
193 }
194 
195 ///////////////////////////////////////////////////////////////////
196 // Full-featured terrain rendering with blending and everything
198 {
199 #if CONFIG2_GLES
200  UNUSED2(filtered);
201 #else
202  ENSURE(m->phase == Phase_Render);
203 
204  std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
205  std::vector<CDecalRData*>& visibleDecals = filtered ? m->filteredDecals : m->visibleDecals;
206  if (visiblePatches.empty() && visibleDecals.empty())
207  return;
208 
209  CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy", CShaderDefines());
210  dummyShader->Bind();
211 
212  // render the solid black sides of the map first
213  g_Renderer.BindTexture(0, 0);
214  glEnableClientState(GL_VERTEX_ARRAY);
215  glColor3f(0, 0, 0);
216  PROFILE_START("render terrain sides");
217  for (size_t i = 0; i < visiblePatches.size(); ++i)
218  visiblePatches[i]->RenderSides(dummyShader);
219  PROFILE_END("render terrain sides");
220 
221  // switch on required client states
222  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
223 
224  // render everything fullbright
225  // set up texture environment for base pass
226  pglActiveTextureARB(GL_TEXTURE0);
227  pglClientActiveTextureARB(GL_TEXTURE0);
228  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
229  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
230  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
231  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
232 
233  // Set alpha to 1.0
234  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
235  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT);
236  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
237  static const float one[4] = { 1.f, 1.f, 1.f, 1.f };
238  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, one);
239 
240  PROFILE_START("render terrain base");
241  CPatchRData::RenderBases(visiblePatches, CShaderDefines(), NULL, true, dummyShader);
242  PROFILE_END("render terrain base");
243 
244  // render blends
245  // switch on the composite alpha map texture
246  (void)ogl_tex_bind(g_Renderer.m_hCompositeAlphaMap, 1);
247 
248  // switch on second uv set
249  pglClientActiveTextureARB(GL_TEXTURE1);
250  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
251 
252  // setup additional texenv required by blend pass
253  pglActiveTextureARB(GL_TEXTURE1);
254  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
255  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
256  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
257  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
258  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
259  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
260  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
261 
262  // switch on blending
263  glEnable(GL_BLEND);
264  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
265 
266  // no need to write to the depth buffer a second time
267  glDepthMask(0);
268 
269  // The decal color array contains lighting data, which we don't want in this non-shader mode
270  glDisableClientState(GL_COLOR_ARRAY);
271 
272  // render blend passes for each patch
273  PROFILE_START("render terrain blends");
274  CPatchRData::RenderBlends(visiblePatches, CShaderDefines(), NULL, true, dummyShader);
275  PROFILE_END("render terrain blends");
276 
277  // Disable second texcoord array
278  pglClientActiveTextureARB(GL_TEXTURE1);
279  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
280 
281 
282  // Render terrain decals
283 
284  g_Renderer.BindTexture(1, 0);
285  pglActiveTextureARB(GL_TEXTURE0);
286  pglClientActiveTextureARB(GL_TEXTURE0);
287  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
288  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
289  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
290  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
291  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
292  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
293  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
294  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
295  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
296 
297  PROFILE_START("render terrain decals");
298  CDecalRData::RenderDecals(visibleDecals, CShaderDefines(), NULL, true, dummyShader);
299  PROFILE_END("render terrain decals");
300 
301 
302  // Now apply lighting
303  const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
304 
305  pglClientActiveTextureARB(GL_TEXTURE0);
306  glEnableClientState(GL_COLOR_ARRAY); // diffuse lighting colours
307 
308  // The vertex color is scaled by 0.5 to permit overbrightness without clamping.
309  // We therefore need to draw clamp((texture*lighting)*2.0), where 'texture'
310  // is what previous passes drew onto the framebuffer, and 'lighting' is the
311  // color computed by this pass.
312  // We can do that with blending by getting it to draw dst*src + src*dst:
313  glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
314 
315  // Scale the ambient color by 0.5 to match the vertex diffuse colors
316  float terrainAmbientColor[4] = {
317  lightEnv.m_TerrainAmbientColor.X * 0.5f,
318  lightEnv.m_TerrainAmbientColor.Y * 0.5f,
319  lightEnv.m_TerrainAmbientColor.Z * 0.5f,
320  1.f
321  };
322 
323  CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();
324 
325  int streamflags = STREAM_POS|STREAM_COLOR;
326 
327  pglActiveTextureARB(GL_TEXTURE0);
328  // We're not going to use a texture here, but we have to have a valid texture
329  // bound else the texture unit will be disabled.
330  // We should still have a bound splat texture from some earlier rendering,
331  // so assume that's still valid to use.
332  // (TODO: That's a bit of an ugly hack.)
333 
334  // No shadows: (Ambient + Diffuse) * LOS
335  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
336  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
337  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
338  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
339  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
340  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
341  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
342  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
343  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
344 
345  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, terrainAmbientColor);
346 
347  losTexture.BindTexture(1);
348  pglClientActiveTextureARB(GL_TEXTURE1);
349  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
350  streamflags |= STREAM_POSTOUV1;
351 
352  glMatrixMode(GL_TEXTURE);
353  glLoadMatrixf(&losTexture.GetTextureMatrix()._11);
354  glMatrixMode(GL_MODELVIEW);
355 
356  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
357  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
358  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
359  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
360  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
361  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
362  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
363  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
364  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
365 
366  pglActiveTextureARB(GL_TEXTURE0);
367  pglClientActiveTextureARB(GL_TEXTURE0);
368 
369  PROFILE_START("render terrain streams");
370  CPatchRData::RenderStreams(visiblePatches, dummyShader, streamflags);
371  PROFILE_END("render terrain streams");
372 
373  glMatrixMode(GL_TEXTURE);
374  glLoadIdentity();
375  glMatrixMode(GL_MODELVIEW);
376 
377  // restore OpenGL state
378  g_Renderer.BindTexture(1, 0);
379 
380  pglClientActiveTextureARB(GL_TEXTURE1);
381  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
382  glMatrixMode(GL_TEXTURE);
383  glLoadIdentity();
384  glMatrixMode(GL_MODELVIEW);
385 
386  pglClientActiveTextureARB(GL_TEXTURE0);
387  pglActiveTextureARB(GL_TEXTURE0);
388 
389  glDepthMask(1);
390  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
391  glDisable(GL_BLEND);
392  glDisableClientState(GL_COLOR_ARRAY);
393  glDisableClientState(GL_VERTEX_ARRAY);
394  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
395 
396  dummyShader->Unbind();
397 #endif
398 }
399 
401 {
402 #if CONFIG2_GLES
403 #warning TODO: implement TerrainRenderer::RenderTerrainOverlayTexture for GLES
404  UNUSED2(textureMatrix);
405 #else
406  ENSURE(m->phase == Phase_Render);
407 
408  std::vector<CPatchRData*>& visiblePatches = m->visiblePatches;
409 
410  glEnableClientState(GL_VERTEX_ARRAY);
411  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
412 
413  glEnable(GL_TEXTURE_2D);
414  glEnable(GL_BLEND);
415  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
416  glDepthMask(0);
417 
418  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
419 
420  glMatrixMode(GL_TEXTURE);
421  glLoadMatrixf(&textureMatrix._11);
422  glMatrixMode(GL_MODELVIEW);
423 
424  CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy", CShaderDefines());
425  dummyShader->Bind();
426  CPatchRData::RenderStreams(visiblePatches, dummyShader, STREAM_POS|STREAM_POSTOUV0);
427  dummyShader->Unbind();
428 
429  // To make the overlay visible over water, render an additional map-sized
430  // water-height patch
431  CBoundingBoxAligned waterBounds;
432  for (size_t i = 0; i < m->visiblePatches.size(); ++i)
433  {
434  CPatchRData* data = m->visiblePatches[i];
435  waterBounds += data->GetWaterBounds();
436  }
437  if (!waterBounds.IsEmpty())
438  {
439  float h = g_Renderer.GetWaterManager()->m_WaterHeight + 0.05f; // add a delta to avoid z-fighting
440  float waterPos[] = {
441  waterBounds[0].X, h, waterBounds[0].Z,
442  waterBounds[1].X, h, waterBounds[0].Z,
443  waterBounds[0].X, h, waterBounds[1].Z,
444  waterBounds[1].X, h, waterBounds[1].Z
445  };
446  glVertexPointer(3, GL_FLOAT, 3*sizeof(float), waterPos);
447  glTexCoordPointer(3, GL_FLOAT, 3*sizeof(float), waterPos);
448  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
449  }
450 
451  glMatrixMode(GL_TEXTURE);
452  glLoadIdentity();
453  glMatrixMode(GL_MODELVIEW);
454 
455  glDepthMask(1);
456  glDisable(GL_BLEND);
457  glDisableClientState(GL_COLOR_ARRAY);
458  glDisableClientState(GL_VERTEX_ARRAY);
459  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
460 #endif
461 }
462 
463 
464 ///////////////////////////////////////////////////////////////////
465 
466 /**
467  * Set up all the uniforms for a shader pass.
468  */
470 {
471  shader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
472  shader->Uniform(str_cameraPos, g_Renderer.GetViewCamera().GetOrientation().GetTranslation());
473 
474  const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
475 
476  if (shadow)
477  {
478  shader->BindTexture(str_shadowTex, shadow->GetTexture());
479  shader->Uniform(str_shadowTransform, shadow->GetTextureMatrix());
480  int width = shadow->GetWidth();
481  int height = shadow->GetHeight();
482  shader->Uniform(str_shadowScale, width, height, 1.0f / width, 1.0f / height);
483  }
484 
485  CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture();
486  shader->BindTexture(str_losTex, los.GetTextureSmooth());
487  shader->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
488 
489  shader->Uniform(str_ambient, lightEnv.m_TerrainAmbientColor);
490  shader->Uniform(str_sunColor, lightEnv.m_SunColor);
491  shader->Uniform(str_sunDir, lightEnv.GetSunDir());
492 
493  shader->Uniform(str_fogColor, lightEnv.m_FogColor);
494  shader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
495 }
496 
497 void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, ShadowMap* shadow, bool filtered)
498 {
499  ENSURE(m->phase == Phase_Render);
500 
501  std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
502  std::vector<CDecalRData*>& visibleDecals = filtered ? m->filteredDecals : m->visibleDecals;
503  if (visiblePatches.empty() && visibleDecals.empty())
504  return;
505 
506  // render the solid black sides of the map first
507  CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid);
508  techSolid->BeginPass();
509  CShaderProgramPtr shaderSolid = techSolid->GetShader();
510  shaderSolid->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
511  shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);
512 
513  PROFILE_START("render terrain sides");
514  for (size_t i = 0; i < visiblePatches.size(); ++i)
515  visiblePatches[i]->RenderSides(shaderSolid);
516  PROFILE_END("render terrain sides");
517 
518  techSolid->EndPass();
519 
520  PROFILE_START("render terrain base");
521  CPatchRData::RenderBases(visiblePatches, context, shadow);
522  PROFILE_END("render terrain base");
523 
524  // no need to write to the depth buffer a second time
525  glDepthMask(0);
526 
527  // render blend passes for each patch
528  PROFILE_START("render terrain blends");
529  CPatchRData::RenderBlends(visiblePatches, context, shadow, false);
530  PROFILE_END("render terrain blends");
531 
532  PROFILE_START("render terrain decals");
533  CDecalRData::RenderDecals(visibleDecals, context, shadow, false);
534  PROFILE_END("render terrain decals");
535 
536  // restore OpenGL state
537  g_Renderer.BindTexture(1, 0);
538  g_Renderer.BindTexture(2, 0);
539  g_Renderer.BindTexture(3, 0);
540 
541  glDepthMask(1);
542  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
543  glDisable(GL_BLEND);
544 }
545 
546 
547 ///////////////////////////////////////////////////////////////////
548 // Render un-textured patches as polygons
550 {
551  ENSURE(m->phase == Phase_Render);
552 
553  std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
554  if (visiblePatches.empty())
555  return;
556 
557 #if CONFIG2_GLES
558 #warning TODO: implement TerrainRenderer::RenderPatches for GLES
559 #else
560  CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy", CShaderDefines());
561  dummyShader->Bind();
562 
563  glEnableClientState(GL_VERTEX_ARRAY);
564  CPatchRData::RenderStreams(visiblePatches, dummyShader, STREAM_POS);
565  glDisableClientState(GL_VERTEX_ARRAY);
566 
567  dummyShader->Unbind();
568 #endif
569 }
570 
571 
572 ///////////////////////////////////////////////////////////////////
573 // Render outlines of submitted patches as lines
575 {
576  ENSURE(m->phase == Phase_Render);
577 
578  std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
579  if (visiblePatches.empty())
580  return;
581 
582 #if CONFIG2_GLES
583 #warning TODO: implement TerrainRenderer::RenderOutlines for GLES
584 #else
585  glEnableClientState(GL_VERTEX_ARRAY);
586  for (size_t i = 0; i < visiblePatches.size(); ++i)
587  visiblePatches[i]->RenderOutline();
588  glDisableClientState(GL_VERTEX_ARRAY);
589 #endif
590 }
591 
592 
593 ///////////////////////////////////////////////////////////////////
594 // Scissor rectangle of water patches
596 {
597  CBoundingBoxAligned scissor;
598  for (size_t i = 0; i < m->visiblePatches.size(); ++i)
599  {
600  CPatchRData* data = m->visiblePatches[i];
601  const CBoundingBoxAligned& waterBounds = data->GetWaterBounds();
602  if (waterBounds.IsEmpty())
603  continue;
604 
605  CVector4D v1 = viewproj.Transform(CVector4D(waterBounds[0].X, waterBounds[1].Y, waterBounds[0].Z, 1.0f));
606  CVector4D v2 = viewproj.Transform(CVector4D(waterBounds[1].X, waterBounds[1].Y, waterBounds[0].Z, 1.0f));
607  CVector4D v3 = viewproj.Transform(CVector4D(waterBounds[0].X, waterBounds[1].Y, waterBounds[1].Z, 1.0f));
608  CVector4D v4 = viewproj.Transform(CVector4D(waterBounds[1].X, waterBounds[1].Y, waterBounds[1].Z, 1.0f));
609  CBoundingBoxAligned screenBounds;
610  #define ADDBOUND(v1, v2, v3, v4) \
611  if (v1.Z >= -v1.W) \
612  screenBounds += CVector3D(v1.X, v1.Y, v1.Z) * (1.0f / v1.W); \
613  else \
614  { \
615  float t = v1.Z + v1.W; \
616  if (v2.Z > -v2.W) \
617  { \
618  CVector4D c2 = v1 + (v2 - v1) * (t / (t - (v2.Z + v2.W))); \
619  screenBounds += CVector3D(c2.X, c2.Y, c2.Z) * (1.0f / c2.W); \
620  } \
621  if (v3.Z > -v3.W) \
622  { \
623  CVector4D c3 = v1 + (v3 - v1) * (t / (t - (v3.Z + v3.W))); \
624  screenBounds += CVector3D(c3.X, c3.Y, c3.Z) * (1.0f / c3.W); \
625  } \
626  if (v4.Z > -v4.W) \
627  { \
628  CVector4D c4 = v1 + (v4 - v1) * (t / (t - (v4.Z + v4.W))); \
629  screenBounds += CVector3D(c4.X, c4.Y, c4.Z) * (1.0f / c4.W); \
630  } \
631  }
632  ADDBOUND(v1, v2, v3, v4);
633  ADDBOUND(v2, v1, v3, v4);
634  ADDBOUND(v3, v1, v2, v4);
635  ADDBOUND(v4, v1, v2, v3);
636  #undef ADDBOUND
637  if (screenBounds[0].X >= 1.0f || screenBounds[1].X <= -1.0f || screenBounds[0].Y >= 1.0f || screenBounds[1].Y <= -1.0f)
638  continue;
639  scissor += screenBounds;
640  }
641  return CBoundingBoxAligned(CVector3D(clamp(scissor[0].X, -1.0f, 1.0f), clamp(scissor[0].Y, -1.0f, 1.0f), -1.0f),
642  CVector3D(clamp(scissor[1].X, -1.0f, 1.0f), clamp(scissor[1].Y, -1.0f, 1.0f), 1.0f));
643 }
644 
645 // Render fancy water
647 {
648  PROFILE3_GPU("fancy water");
649 
650  WaterManager* WaterMgr = g_Renderer.GetWaterManager();
651  CShaderDefines defines = context;
652 
653  WaterMgr->UpdateQuality();
654 
655  // If we're using fancy water, make sure its shader is loaded
656  if (!m->fancyWaterShader || WaterMgr->m_NeedsReloading)
657  {
658  if (WaterMgr->m_WaterNormal)
659  defines.Add(str_USE_NORMALS, str_1);
660  if (WaterMgr->m_WaterRealDepth)
661  defines.Add(str_USE_REAL_DEPTH, str_1);
662  if (WaterMgr->m_WaterFoam && !g_AtlasGameLoop->running)
663  defines.Add(str_USE_FOAM, str_1);
664  if (WaterMgr->m_WaterCoastalWaves && !g_AtlasGameLoop->running)
665  defines.Add(str_USE_WAVES, str_1);
666  if (WaterMgr->m_WaterRefraction)
667  defines.Add(str_USE_REFRACTION, str_1);
668  if (WaterMgr->m_WaterReflection)
669  defines.Add(str_USE_REFLECTION, str_1);
670  if (shadow && WaterMgr->m_WaterShadows)
671  defines.Add(str_USE_SHADOWS, str_1);
672 
673  m->wavesShader = g_Renderer.GetShaderManager().LoadProgram("glsl/waves", defines);
674  if (!m->wavesShader)
675  {
676  LOGERROR(L"Failed to load waves shader. Deactivating waves.\n");
677  g_Renderer.SetOptionBool(CRenderer::OPT_WATERCOASTALWAVES, false);
678  defines.Add(str_USE_WAVES, str_0);
679  }
680 
681  // haven't updated the ARB shader yet so I'll always load the GLSL
682  /*if (!g_Renderer.m_Options.m_PreferGLSL && !superFancy)
683  m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("arb/water_high", defines);
684  else*/
685  m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("glsl/water_high", defines);
686 
687  if (!m->fancyWaterShader)
688  {
689  LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n");
690  WaterMgr->m_RenderWater = false;
691  return false;
692  }
693  WaterMgr->m_NeedsReloading = false;
694  }
695 
696  CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();
697 
698  GLuint depthTex;
699  // creating the real depth texture using the depth buffer.
700  if (WaterMgr->m_WaterRealDepth)
701  {
702  if (WaterMgr->m_depthTT == 0)
703  {
704  glGenTextures(1, (GLuint*)&depthTex);
705  WaterMgr->m_depthTT = depthTex;
706  glBindTexture(GL_TEXTURE_2D, WaterMgr->m_depthTT);
707  // TODO: use POT texture
708  glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, g_Renderer.GetWidth(), g_Renderer.GetHeight(),
709  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE,NULL);
710  }
711  glBindTexture(GL_TEXTURE_2D, WaterMgr->m_depthTT);
712  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
713  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
714  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
715  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
716  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
717 
718  glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight(), 0);
719 
720  glBindTexture(GL_TEXTURE_2D, 0);
721  }
722  // Calculating the advanced informations about Foam and all if the quality calls for it.
723  /*if (WaterMgr->m_NeedInfoUpdate && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves))
724  {
725  WaterMgr->m_NeedInfoUpdate = false;
726  WaterMgr->CreateSuperfancyInfo();
727  }*/
728 
729  glEnable(GL_BLEND);
730  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
731  glEnable(GL_DEPTH_TEST);
732  glDepthFunc(GL_LEQUAL);
733 
734  double time = WaterMgr->m_WaterTexTimer;
735  double period = 8;
736  int curTex = (int)(time*60/period) % 60;
737  int nexTex = (curTex + 1) % 60;
738 
739  GLuint FramebufferName = 0;
740 
741  // rendering waves to a framebuffer
742  if (WaterMgr->m_WaterCoastalWaves && WaterMgr->m_VBWaves && !g_AtlasGameLoop->running)
743  {
744  // Save the post-processing framebuffer.
745  GLint fbo;
746  glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fbo);
747 
748  pglGenFramebuffersEXT(1, &FramebufferName);
749  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferName);
750 
751  GLuint renderedTexture;
752  if (WaterMgr->m_waveTT == 0)
753  {
754  glGenTextures(1, &renderedTexture);
755  WaterMgr->m_waveTT = renderedTexture;
756 
757  glBindTexture(GL_TEXTURE_2D, WaterMgr->m_waveTT);
758  // TODO: use POT texture
759  glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);
760 
761  }
762  glBindTexture(GL_TEXTURE_2D, WaterMgr->m_waveTT);
763 
764  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
765  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
766 
767  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, WaterMgr->m_waveTT, 0);
768 
769  glClearColor(0.5f,0.5f,1.0f,0.0f);
770  glClear(GL_COLOR_BUFFER_BIT);
771 
772  // rendering
773  m->wavesShader->Bind();
774  m->wavesShader->BindTexture(str_waveTex, WaterMgr->m_Wave);
775  m->wavesShader->Uniform(str_time, (float)time);
776  m->wavesShader->Uniform(str_waviness, WaterMgr->m_Waviness);
777  m->wavesShader->Uniform(str_mapSize, (float)(WaterMgr->m_TexSize));
778 
779  SWavesVertex *base=(SWavesVertex *)WaterMgr->m_VBWaves->m_Owner->Bind();
780  GLsizei stride = sizeof(SWavesVertex);
781  m->wavesShader->VertexPointer(3, GL_FLOAT, stride, &base[WaterMgr->m_VBWaves->m_Index].m_Position);
782  m->wavesShader->TexCoordPointer(GL_TEXTURE0,2,GL_BYTE, stride,&base[WaterMgr->m_VBWaves->m_Index].m_UV);
783  m->wavesShader->AssertPointersBound();
784  u8* indexBase = WaterMgr->m_VBWavesIndices->m_Owner->Bind();
785  glDrawElements(GL_QUADS, (GLsizei) WaterMgr->m_VBWavesIndices->m_Count, GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(WaterMgr->m_VBWavesIndices->m_Index));
786  g_Renderer.m_Stats.m_DrawCalls++;
788  m->wavesShader->Unbind();
789 
790  // rebind post-processing frambuffer.
791  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
792  glBindTexture(GL_TEXTURE_2D, 0);
793 
794  }
795 
796  m->fancyWaterShader->Bind();
797 
798 
799  // Shift the texture coordinates by these amounts to make the water "flow"
800  float tx = -fmod(time, 81.0 / (WaterMgr->m_Waviness/20.0 + 0.8) )/(81.0/ (WaterMgr->m_Waviness/20.0 + 0.8) );
801  float ty = -fmod(time, 34.0 / (WaterMgr->m_Waviness/20.0 + 0.8) )/(34.0/ (WaterMgr->m_Waviness/20.0 + 0.8) );
802 
803  float repeatPeriod = WaterMgr->m_RepeatPeriod;
804 
805  const CCamera& camera = g_Renderer.GetViewCamera();
806  CVector3D camPos = camera.m_Orientation.GetTranslation();
807 
808  m->fancyWaterShader->BindTexture(str_normalMap, WaterMgr->m_NormalMap[curTex]);
809  m->fancyWaterShader->BindTexture(str_normalMap2, WaterMgr->m_NormalMap[nexTex]);
810 
811  if (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves)
812  {
813  m->fancyWaterShader->BindTexture(str_Foam, WaterMgr->m_Foam);
814  m->fancyWaterShader->Uniform(str_mapSize, (float)(WaterMgr->m_TexSize));
815  }
816  if (WaterMgr->m_WaterRealDepth)
817  m->fancyWaterShader->BindTexture(str_depthTex, WaterMgr->m_depthTT);
818  if (WaterMgr->m_WaterCoastalWaves)
819  m->fancyWaterShader->BindTexture(str_waveTex, WaterMgr->m_waveTT);
820  if (WaterMgr->m_WaterReflection)
821  m->fancyWaterShader->BindTexture(str_reflectionMap, WaterMgr->m_ReflectionTexture);
822  if (WaterMgr->m_WaterRefraction)
823  m->fancyWaterShader->BindTexture(str_refractionMap, WaterMgr->m_RefractionTexture);
824 
825  m->fancyWaterShader->BindTexture(str_losMap, losTexture.GetTextureSmooth());
826 
827  const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
828 
829  // TODO: only bind what's really needed for that.
830  m->fancyWaterShader->Uniform(str_sunDir, lightEnv.GetSunDir());
831  m->fancyWaterShader->Uniform(str_sunColor, lightEnv.m_SunColor.X);
832  m->fancyWaterShader->Uniform(str_color, WaterMgr->m_WaterColor);
833  m->fancyWaterShader->Uniform(str_shininess, WaterMgr->m_Shininess);
834  m->fancyWaterShader->Uniform(str_specularStrength, WaterMgr->m_SpecularStrength);
835  m->fancyWaterShader->Uniform(str_waviness, WaterMgr->m_Waviness);
836  m->fancyWaterShader->Uniform(str_murkiness, WaterMgr->m_Murkiness);
837  m->fancyWaterShader->Uniform(str_tint, WaterMgr->m_WaterTint);
838  m->fancyWaterShader->Uniform(str_reflectionTintStrength, WaterMgr->m_ReflectionTintStrength);
839  m->fancyWaterShader->Uniform(str_reflectionTint, WaterMgr->m_ReflectionTint);
840  m->fancyWaterShader->Uniform(str_translation, tx, ty);
841  m->fancyWaterShader->Uniform(str_repeatScale, 1.0f / repeatPeriod);
842  m->fancyWaterShader->Uniform(str_reflectionMatrix, WaterMgr->m_ReflectionMatrix);
843  m->fancyWaterShader->Uniform(str_refractionMatrix, WaterMgr->m_RefractionMatrix);
844  m->fancyWaterShader->Uniform(str_losMatrix, losTexture.GetTextureMatrix());
845  m->fancyWaterShader->Uniform(str_cameraPos, camPos);
846  m->fancyWaterShader->Uniform(str_fogColor, lightEnv.m_FogColor);
847  m->fancyWaterShader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
848  m->fancyWaterShader->Uniform(str_time, (float)time);
849  m->fancyWaterShader->Uniform(str_screenSize, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f);
850  m->fancyWaterShader->BindTexture(str_skyCube, g_Renderer.GetSkyManager()->GetSkyCube());
851 
852  if (shadow && WaterMgr->m_WaterShadows)
853  {
854  m->fancyWaterShader->BindTexture(str_shadowTex, shadow->GetTexture());
855  m->fancyWaterShader->Uniform(str_shadowTransform, shadow->GetTextureMatrix());
856  int width = shadow->GetWidth();
857  int height = shadow->GetHeight();
858  m->fancyWaterShader->Uniform(str_shadowScale, width, height, 1.0f / width, 1.0f / height);
859  }
860 
861  for (size_t i = 0; i < m->visiblePatches.size(); ++i)
862  {
863  CPatchRData* data = m->visiblePatches[i];
865  }
866 
867  m->fancyWaterShader->Unbind();
868 
869  pglActiveTextureARB(GL_TEXTURE0);
870  pglDeleteFramebuffersEXT(1, &FramebufferName);
871 
872  glDisable(GL_BLEND);
873 
874  return true;
875 }
876 
878 {
879 #if !CONFIG2_GLES
880  PROFILE3_GPU("simple water");
881 
882  WaterManager* WaterMgr = g_Renderer.GetWaterManager();
883  CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
884 
885  glEnable(GL_BLEND);
886  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
887  glEnable(GL_DEPTH_TEST);
888  glDepthFunc(GL_LEQUAL);
889 
890  double time = WaterMgr->m_WaterTexTimer;
891  double period = 1.6f;
892  int curTex = (int)(time*60/period) % 60;
893 
894  WaterMgr->m_WaterTexture[curTex]->Bind();
895 
896  // Shift the texture coordinates by these amounts to make the water "flow"
897  float tx = -fmod(time, 81.0)/81.0;
898  float ty = -fmod(time, 34.0)/34.0;
899  float repeatPeriod = 16.0f;
900 
901  // Perform the shifting by using texture coordinate generation
902  GLfloat texgenS0[4] = { 1/repeatPeriod, 0, 0, tx };
903  GLfloat texgenT0[4] = { 0, 0, 1/repeatPeriod, ty };
904  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
905  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
906  glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS0);
907  glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT0);
908  glEnable(GL_TEXTURE_GEN_S);
909  glEnable(GL_TEXTURE_GEN_T);
910 
911  // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha
912  GLfloat waterColor[4] = { WaterMgr->m_WaterColor.r, WaterMgr->m_WaterColor.g, WaterMgr->m_WaterColor.b, 1.0f };
913  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, waterColor);
914  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
915  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
916  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
917  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
918  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
919  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
920  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
921  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
922  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
923 
924  // Multiply by LOS texture
925  losTexture.BindTexture(1);
926  CMatrix3D losMatrix = losTexture.GetTextureMatrix();
927  GLfloat texgenS1[4] = { losMatrix[0], losMatrix[4], losMatrix[8], losMatrix[12] };
928  GLfloat texgenT1[4] = { losMatrix[1], losMatrix[5], losMatrix[9], losMatrix[13] };
929  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
930  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
931  glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1);
932  glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1);
933  glEnable(GL_TEXTURE_GEN_S);
934  glEnable(GL_TEXTURE_GEN_T);
935 
936  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
937  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
938  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
939  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
940  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
941  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
942  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
943  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
944  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
945 
946  CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy", CShaderDefines());
947  dummyShader->Bind();
948 
949  glEnableClientState(GL_VERTEX_ARRAY);
950  glEnableClientState(GL_COLOR_ARRAY);
951 
952  for (size_t i = 0; i < m->visiblePatches.size(); ++i)
953  {
954  CPatchRData* data = m->visiblePatches[i];
955  data->RenderWater(dummyShader);
956  }
957 
958  glDisableClientState(GL_COLOR_ARRAY);
959  glDisableClientState(GL_VERTEX_ARRAY);
960 
961  dummyShader->Unbind();
962 
963  g_Renderer.BindTexture(1, 0);
964 
965  glDisable(GL_TEXTURE_GEN_S);
966  glDisable(GL_TEXTURE_GEN_T);
967  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
968 
969  pglActiveTextureARB(GL_TEXTURE0_ARB);
970 
971  // Clean up the texture matrix and blend mode
972  glDisable(GL_TEXTURE_GEN_S);
973  glDisable(GL_TEXTURE_GEN_T);
974  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
975 
976  glDisable(GL_BLEND);
977  glDisable(GL_TEXTURE_2D);
978 #endif
979 }
980 
981 ///////////////////////////////////////////////////////////////////
982 // Render water that is part of the terrain
984 {
985  WaterManager* WaterMgr = g_Renderer.GetWaterManager();
986 
987  if (!WaterMgr->WillRenderFancyWater())
989  else
990  RenderFancyWater(context, shadow);
991 }
992 
994 {
995  PROFILE("priorities");
996 
997  ENSURE(m->phase == Phase_Render);
998 
999  CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);
1000  tech->BeginPass();
1001  CTextRenderer textRenderer(tech->GetShader());
1002 
1003  textRenderer.Font(L"mono-stroke-10");
1004  textRenderer.Color(1.0f, 1.0f, 0.0f);
1005 
1006  for (size_t i = 0; i < m->visiblePatches.size(); ++i)
1007  m->visiblePatches[i]->RenderPriorities(textRenderer);
1008 
1009  textRenderer.Render();
1010  tech->EndPass();
1011 }
CTexturePtr m_WaterTexture[60]
Definition: WaterManager.h:52
void Add(CStrIntern name, CStrIntern value)
Add a name and associated value to the map of defines.
#define u8
Definition: types.h:39
static void RenderBases(const std::vector< CPatchRData * > &patches, const CShaderDefines &context, ShadowMap *shadow, bool isDummyShader=false, const CShaderProgramPtr &dummy=CShaderProgramPtr())
Definition: PatchRData.cpp:721
size_t m_Index
Start index of this chunk in owner.
Definition: VertexBuffer.h:52
const CVector3D & GetSunDir() const
Definition: LightEnv.h:84
Definition: Decompose.h:22
float m_RepeatPeriod
Definition: WaterManager.h:117
void RenderWater(CShaderProgramPtr &shader)
void RenderOutlines(bool filtered=false)
RenderOutlines: Render the outline of patches as lines.
float g
Definition: Overlay.h:57
float m_Shininess
Definition: WaterManager.h:118
void RenderWater(const CShaderDefines &context, ShadowMap *shadow)
RenderWater: Render water for all patches that have been submitted this frame.
const CBoundingBoxAligned & GetWaterBounds() const
Definition: PatchRData.h:60
void PrepareForRendering()
PrepareForRendering: Prepare internal data structures like vertex buffers for rendering.
Definition: Decompose.h:22
#define LOGERROR
Definition: CLogger.h:35
GLuint m_depthTT
Definition: WaterManager.h:64
bool m_WaterRealDepth
Definition: WaterManager.h:79
friend class CPatchRData
RGBColor m_TerrainAmbientColor
Definition: LightEnv.h:70
GLuint GetTextureSmooth()
Definition: LOSTexture.cpp:106
CVertexBuffer::VBChunk * m_VBWaves
Definition: WaterManager.h:127
float m_Waviness
Definition: WaterManager.h:120
Struct TerrainRendererInternals: Internal variables used by the TerrainRenderer class.
void RenderTerrainShader(const CShaderDefines &context, ShadowMap *shadow, bool filtered=false)
Render textured terrain, as with RenderTerrain, but using shaders instead of multitexturing.
bool m_WaterShadows
Definition: WaterManager.h:84
bool m_WaterNormal
Definition: WaterManager.h:78
bool IsBoxVisible(const CVector3D &position, const CBoundingBoxAligned &bounds) const
Definition: Frustum.cpp:116
GLuint GetTexture() const
GetTexture: Retrieve the OpenGL texture object name that contains the shadow map. ...
Definition: ShadowMap.cpp:524
CVector3D Transform(const CVector3D &vector) const
Definition: Matrix3D.h:272
CTexturePtr m_NormalMap[60]
Definition: WaterManager.h:53
GameLoopState * g_AtlasGameLoop
shared_ptr< CShaderTechnique > CShaderTechniquePtr
GLuint m_RefractionTexture
Definition: WaterManager.h:106
RGBColor m_SunColor
Definition: LightEnv.h:69
void RenderTerrain(bool filtered=false)
RenderTerrain: Render textured terrain (including blends between different terrain types)...
Class ShadowMap: Maintain the shadow map texture and perform necessary OpenGL setup, including matrix calculations.
Definition: ShadowMap.h:39
#define PROFILE_END(name)
Definition: Profile.h:198
u8 * Bind()
Bind to this buffer; return pointer to address required as parameter to glVertexPointer ( + etc) call...
float _11
Definition: Matrix3D.h:42
bool m_WaterFoam
Definition: WaterManager.h:80
CMatrix3D m_ReflectionMatrix
Definition: WaterManager.h:112
Public API for simulation system.
Definition: Simulation2.h:46
#define g_Renderer
Definition: Renderer.h:61
CTexturePtr m_Foam
Definition: WaterManager.h:54
void Update(CSimulation2 *simulation)
Definition: DecalRData.cpp:63
Status ogl_tex_bind(Handle ht, size_t unit)
Bind texture to the specified unit in preparation for using it in rendering.
Definition: ogl_tex.cpp:1054
RGBColor m_FogColor
Definition: LightEnv.h:72
CShaderProgramPtr wavesShader
bool m_NeedsReloading
Definition: WaterManager.h:86
float m_Murkiness
Definition: WaterManager.h:121
void RenderPatches(bool filtered=false)
RenderPatches: Render all patches un-textured as polygons.
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
int GetWidth() const
GetWidth: Return the width of the depth texture.
Definition: ShadowMap.cpp:559
#define UNUSED2(param)
mark a function local variable or parameter as unused and avoid the corresponding compiler warning...
std::vector< CPatchRData * > visiblePatches
Patches that were submitted for this frame.
CRenderData * GetRenderData()
Return object renderdata - can be null if renderer hasn&#39;t yet created the renderdata.
void UpdateQuality()
Updates the settings to the one from the renderer, and sets m_NeedsReloading.
float b
Definition: Overlay.h:57
void RenderPriorities()
Render priority text for all submitted patches, for debugging.
bool CullPatches(const CFrustum *frustum)
CullPatches: Culls patches and decals against a frustum, and stores the results in a special filtered...
bool m_RenderWater
Definition: WaterManager.h:75
float X
Definition: Vector3D.h:31
GLuint m_waveTT
Definition: WaterManager.h:65
void Update(CSimulation2 *simulation)
Definition: PatchRData.cpp:662
CMatrix3D m_RefractionMatrix
Definition: WaterManager.h:113
friend class CDecalRData
CColor m_WaterTint
Definition: WaterManager.h:116
float m_FogMax
Definition: LightEnv.h:75
float Y
Definition: Vector3D.h:31
CShaderProgramPtr fancyWaterShader
Fancy water shader.
Definition: Camera.h:39
bool m_WaterRefraction
Definition: WaterManager.h:82
void SetRenderData(CRenderData *renderdata)
void EndFrame()
EndFrame: Remove all patches from the list of submitted patches.
Definition: Patch.h:48
#define PROFILE_START(name)
Definition: Profile.h:197
CGame * g_Game
Globally accessible pointer to the CGame object.
Definition: Game.cpp:56
#define PROFILE(name)
Definition: Profile.h:195
void RenderTerrainOverlayTexture(CMatrix3D &textureMatrix)
Render texture unit 0 over the terrain mesh, with UV coords calculated by the given texture matrix...
#define ADDBOUND(v1, v2, v3, v4)
float m_SpecularStrength
Definition: WaterManager.h:119
size_t m_Count
Number of vertices used by chunk.
Definition: VertexBuffer.h:54
void Submit(CPatch *patch)
Submit: Add a patch for rendering in this frame.
static void RenderBlends(const std::vector< CPatchRData * > &patches, const CShaderDefines &context, ShadowMap *shadow, bool isDummyShader=false, const CShaderProgramPtr &dummy=CShaderProgramPtr())
Definition: PatchRData.cpp:898
Represents a mapping of name strings to value strings, for use with #if and #ifdef and similar condit...
#define u16
Definition: types.h:40
const CMatrix3D & GetTextureMatrix() const
GetTextureMatrix: Retrieve the world-space to shadow map texture coordinates transformation matrix...
Definition: ShadowMap.cpp:529
CGameView * GetView()
Get the pointer to the game view object.
Definition: Game.h:128
void RenderSimpleWater()
RenderSimpleWater: internal rendering method for water.
bool WillRenderFancyWater()
Returns true if fancy water shaders will be used (i.e.
static void PrepareShader(const CShaderProgramPtr &shader, ShadowMap *shadow)
Set up all the uniforms for a shader pass.
Phase phase
Which phase (submitting or rendering patches) are we in right now?
Definition: Decompose.h:22
float m_ReflectionTintStrength
Definition: WaterManager.h:123
GLuint m_ReflectionTexture
Definition: WaterManager.h:105
void Font(const CStrW &font)
Set the font for subsequent print calls.
virtual CLOSTexture & GetLOSTexture()
Return the LOS texture to be used for rendering this scene.
Definition: GameView.cpp:400
CVertexBuffer * m_Owner
Owning (parent) vertex buffer.
Definition: VertexBuffer.h:50
float m_FogFactor
Definition: LightEnv.h:74
std::vector< CDecalRData * > visibleDecals
Decals that were submitted for this frame.
CVertexBuffer::VBChunk * m_VBWavesIndices
Definition: WaterManager.h:128
CTexturePtr m_Wave
Definition: WaterManager.h:55
bool m_WaterReflection
Definition: WaterManager.h:83
CColor m_WaterColor
Definition: WaterManager.h:74
void BindTexture(int unit)
Recomputes the LOS texture if necessary, and binds it to the requested texture unit.
Definition: LOSTexture.cpp:95
CMatrix3D m_Orientation
Definition: Camera.h:112
float Z
Definition: Vector3D.h:31
Maintains the LOS (fog-of-war / shroud-of-darkness) texture, used for rendering and for the minimap...
Definition: LOSTexture.h:32
double m_WaterTexTimer
Definition: WaterManager.h:102
#define PROFILE3_GPU(name)
Definition: Profile.h:204
bool RenderFancyWater(const CShaderDefines &context, ShadowMap *shadow)
RenderFancyWater: internal rendering method for fancy water.
const CMatrix3D & GetTextureMatrix()
Returns a matrix to map (x,y,z) world coordinates onto (u,v) LOS texture coordinates, in the form expected by glLoadMatrixf.
Definition: LOSTexture.cpp:184
static void Unbind()
Unbind any currently-bound buffer, so glVertexPointer etc calls will not attempt to use it...
std::vector< CPatchRData * > filteredPatches
CVector3D GetTranslation() const
Definition: Matrix3D.cpp:195
Class CLightEnv: description of a lighting environment - contains all the necessary parameters for re...
Definition: LightEnv.h:36
static void RenderDecals(std::vector< CDecalRData * > &decals, const CShaderDefines &context, ShadowMap *shadow, bool isDummyShader=false, const CShaderProgramPtr &dummy=CShaderProgramPtr())
Definition: DecalRData.cpp:73
static void RenderStreams(const std::vector< CPatchRData * > &patches, const CShaderProgramPtr &shader, int streamflags)
Phase
TerrainRenderer keeps track of which phase it is in, to detect when Submit, PrepareForRendering etc...
CBoundingBoxAligned ScissorWater(const CMatrix3D &viewproj)
Calculate a scissor rectangle for the visible water patches.
shared_ptr< CShaderProgram > CShaderProgramPtr
int GetHeight() const
GetHeight: Return the height of the depth texture.
Definition: ShadowMap.cpp:564
T clamp(T value, T min, T max)
Definition: MathUtil.h:32
void SetSimulation(CSimulation2 *simulation)
Set the simulation context for this frame.
ssize_t m_TexSize
Definition: WaterManager.h:62
CVector3D m_Position
Definition: WaterManager.h:35
float r
Definition: Overlay.h:57
bool m_WaterCoastalWaves
Definition: WaterManager.h:81
std::vector< CDecalRData * > filteredDecals
Class WaterManager: Maintain water settings and textures.
Definition: WaterManager.h:49
CColor m_ReflectionTint
Definition: WaterManager.h:122
TerrainRendererInternals * m