Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ShadowMap.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 /*
19  * Shadow mapping related texture and matrix management
20  */
21 
22 #include "precompiled.h"
23 
24 #include "gui/GUIutil.h"
25 #include "lib/bits.h"
26 #include "lib/ogl.h"
27 #include "ps/CLogger.h"
28 #include "ps/Profile.h"
29 
30 #include "graphics/LightEnv.h"
31 #include "graphics/ShaderManager.h"
32 
34 #include "maths/MathUtil.h"
35 #include "maths/Matrix3D.h"
36 
37 #include "renderer/Renderer.h"
38 #include "renderer/ShadowMap.h"
39 
40 
41 ///////////////////////////////////////////////////////////////////////////////////////////////////
42 // ShadowMap implementation
43 
44 /**
45  * Struct ShadowMapInternals: Internal data for the ShadowMap implementation
46  */
48 {
49  // bit depth for the depth texture
51  // the EXT_framebuffer_object framebuffer
52  GLuint Framebuffer;
53  // handle of shadow map
54  GLuint Texture;
55  // width, height of shadow map
56  int Width, Height;
57  // used width, height of shadow map
59  // transform light space into projected light space
60  // in projected light space, the shadowbound box occupies the [-1..1] cube
61  // calculated on BeginRender, after the final shadow bounds are known
63  // Transform world space into light space; calculated on SetupFrame
65  // Transform world space into texture space of the shadow map;
66  // calculated on BeginRender, after the final shadow bounds are known
68 
69  // transform light space into world space
71  // bounding box of shadowed objects in light space
73 
74  // Camera transformed into light space
76 
77  // Some drivers (at least some Intel Mesa ones) appear to handle alpha testing
78  // incorrectly when the FBO has only a depth attachment.
79  // When m_ShadowAlphaFix is true, we use DummyTexture to store a useless
80  // alpha texture which is attached to the FBO as a workaround.
81  GLuint DummyTexture;
82 
83  // Copy of renderer's standard view camera, saved between
84  // BeginRender and EndRender while we replace it with the shadow camera
86 
87  // Save the caller's FBO so it can be restored
88  GLint SavedViewFBO;
89 
90  // Helper functions
91  void CalcShadowMatrices();
92  void CreateTexture();
93 };
94 
95 
96 ///////////////////////////////////////////////////////////////////////////////////////////////////
97 // Construction/Destruction
99 {
100  m = new ShadowMapInternals;
101  m->Framebuffer = 0;
102  m->Texture = 0;
103  m->DummyTexture = 0;
104  m->Width = 0;
105  m->Height = 0;
106  m->EffectiveWidth = 0;
107  m->EffectiveHeight = 0;
108  m->DepthTextureBits = 0;
109  // DepthTextureBits: 24/32 are very much faster than 16, on GeForce 4 and FX;
110  // but they're very much slower on Radeon 9800.
111  // In both cases, the default (no specified depth) is fast, so we just use
112  // that by default and hope it's alright. (Otherwise, we'd probably need to
113  // do some kind of hardware detection to work out what to use.)
114 
115  // Avoid using uninitialised values in AddShadowedBound if SetupFrame wasn't called first
117 }
118 
119 
121 {
122  if (m->Texture)
123  glDeleteTextures(1, &m->Texture);
124  if (m->DummyTexture)
125  glDeleteTextures(1, &m->DummyTexture);
126  if (m->Framebuffer)
127  pglDeleteFramebuffersEXT(1, &m->Framebuffer);
128 
129  delete m;
130 }
131 
132 ///////////////////////////////////////////////////////////////////////////////////////////////////
133 // Force the texture/buffer/etc to be recreated, particularly when the renderer's
134 // size has changed
136 {
137  if (m->Texture)
138  glDeleteTextures(1, &m->Texture);
139  if (m->DummyTexture)
140  glDeleteTextures(1, &m->DummyTexture);
141  if (m->Framebuffer)
142  pglDeleteFramebuffersEXT(1, &m->Framebuffer);
143 
144  m->Texture = 0;
145  m->DummyTexture = 0;
146  m->Framebuffer = 0;
147 
148  // (Texture will be constructed in next SetupFrame)
149 }
150 
151 //////////////////////////////////////////////////////////////////////////////
152 // SetupFrame: camera and light direction for this frame
153 void ShadowMap::SetupFrame(const CCamera& camera, const CVector3D& lightdir)
154 {
155  if (!m->Texture)
156  m->CreateTexture();
157 
158  CVector3D z = lightdir;
159  CVector3D y;
160  CVector3D x = camera.m_Orientation.GetIn();
161  CVector3D eyepos = camera.m_Orientation.GetTranslation();
162 
163  z.Normalize();
164  x -= z * z.Dot(x);
165  if (x.Length() < 0.001)
166  {
167  // this is invoked if the camera and light directions almost coincide
168  // assumption: light direction has a significant Z component
169  x = CVector3D(1.0, 0.0, 0.0);
170  x -= z * z.Dot(x);
171  }
172  x.Normalize();
173  y = z.Cross(x);
174 
175  // X axis perpendicular to light direction, flowing along with view direction
176  m->LightTransform._11 = x.X;
177  m->LightTransform._12 = x.Y;
178  m->LightTransform._13 = x.Z;
179 
180  // Y axis perpendicular to light and view direction
181  m->LightTransform._21 = y.X;
182  m->LightTransform._22 = y.Y;
183  m->LightTransform._23 = y.Z;
184 
185  // Z axis is in direction of light
186  m->LightTransform._31 = z.X;
187  m->LightTransform._32 = z.Y;
188  m->LightTransform._33 = z.Z;
189 
190  // eye is at the origin of the coordinate system
191  m->LightTransform._14 = -x.Dot(eyepos);
192  m->LightTransform._24 = -y.Dot(eyepos);
193  m->LightTransform._34 = -z.Dot(eyepos);
194 
195  m->LightTransform._41 = 0.0;
196  m->LightTransform._42 = 0.0;
197  m->LightTransform._43 = 0.0;
198  m->LightTransform._44 = 1.0;
199 
202 
203  //
204  m->LightspaceCamera = camera;
207 }
208 
209 
210 //////////////////////////////////////////////////////////////////////////////
211 // AddShadowedBound: add a world-space bounding box to the bounds of shadowed
212 // objects
214 {
215  CBoundingBoxAligned lightspacebounds;
216 
217  bounds.Transform(m->LightTransform, lightspacebounds);
218  m->ShadowBound += lightspacebounds;
219 }
220 
221 
222 ///////////////////////////////////////////////////////////////////////////////////////////////////
223 // CalcShadowMatrices: calculate required matrices for shadow map generation - the light's
224 // projection and transformation matrices
226 {
227  float minZ = ShadowBound[0].Z;
228 
230 
231  // ShadowBound might have been empty to begin with, producing an empty result
232  if (ShadowBound.IsEmpty())
233  {
234  // no-op
237  return;
238  }
239 
240  // round off the shadow boundaries to sane increments to help reduce swim effect
241  float boundInc = 16.0f;
242  ShadowBound[0].X = floor(ShadowBound[0].X / boundInc) * boundInc;
243  ShadowBound[0].Y = floor(ShadowBound[0].Y / boundInc) * boundInc;
244  ShadowBound[1].X = ceil(ShadowBound[1].X / boundInc) * boundInc;
245  ShadowBound[1].Y = ceil(ShadowBound[1].Y / boundInc) * boundInc;
246 
247  // minimum Z bound must not be clipped too much, because objects that lie outside
248  // the shadow bounds cannot cast shadows either
249  // the 2.0 is rather arbitrary: it should be big enough so that we won't accidentally miss
250  // a shadow generator, and small enough not to affect Z precision
251  ShadowBound[0].Z = minZ - 2.0;
252 
253  // Setup orthogonal projection (lightspace -> clip space) for shadowmap rendering
254  CVector3D scale = ShadowBound[1] - ShadowBound[0];
255  CVector3D shift = (ShadowBound[1] + ShadowBound[0]) * -0.5;
256 
257  if (scale.X < 1.0)
258  scale.X = 1.0;
259  if (scale.Y < 1.0)
260  scale.Y = 1.0;
261  if (scale.Z < 1.0)
262  scale.Z = 1.0;
263 
264  scale.X = 2.0 / scale.X;
265  scale.Y = 2.0 / scale.Y;
266  scale.Z = 2.0 / scale.Z;
267 
268  // make sure a given world position falls on a consistent shadowmap texel fractional offset
269  float offsetX = fmod(ShadowBound[0].X - LightTransform._14, 2.0f/(scale.X*EffectiveWidth));
270  float offsetY = fmod(ShadowBound[0].Y - LightTransform._24, 2.0f/(scale.Y*EffectiveHeight));
271 
273  LightProjection._11 = scale.X;
274  LightProjection._14 = (shift.X + offsetX) * scale.X;
275  LightProjection._22 = scale.Y;
276  LightProjection._24 = (shift.Y + offsetY) * scale.Y;
277  LightProjection._33 = scale.Z;
278  LightProjection._34 = shift.Z * scale.Z;
279  LightProjection._44 = 1.0;
280 
281  // Calculate texture matrix by creating the clip space to texture coordinate matrix
282  // and then concatenating all matrices that have been calculated so far
283 
284  float texscalex = scale.X * 0.5f * (float)EffectiveWidth / (float)Width;
285  float texscaley = scale.Y * 0.5f * (float)EffectiveHeight / (float)Height;
286  float texscalez = scale.Z * 0.5f;
287 
288  CMatrix3D lightToTex;
289  lightToTex.SetZero();
290  lightToTex._11 = texscalex;
291  lightToTex._14 = (offsetX - ShadowBound[0].X) * texscalex;
292  lightToTex._22 = texscaley;
293  lightToTex._24 = (offsetY - ShadowBound[0].Y) * texscaley;
294  lightToTex._33 = texscalez;
295  lightToTex._34 = -ShadowBound[0].Z * texscalez;
296  lightToTex._44 = 1.0;
297 
298  TextureMatrix = lightToTex * LightTransform;
299 }
300 
301 
302 
303 //////////////////////////////////////////////////////////////////////////
304 // Create the shadow map
306 {
307  // Cleanup
308  if (Texture)
309  {
310  glDeleteTextures(1, &Texture);
311  Texture = 0;
312  }
313  if (DummyTexture)
314  {
315  glDeleteTextures(1, &DummyTexture);
316  DummyTexture = 0;
317  }
318  if (Framebuffer)
319  {
320  pglDeleteFramebuffersEXT(1, &Framebuffer);
321  Framebuffer = 0;
322  }
323 
324  // save the caller's FBO
325  glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &SavedViewFBO);
326 
327  pglGenFramebuffersEXT(1, &Framebuffer);
328 
329  if (g_Renderer.m_ShadowMapSize != 0)
330  {
331  // non-default option to override the size
332  Width = Height = g_Renderer.m_ShadowMapSize;
333  }
334  else
335  {
336  // get shadow map size as next power of two up from view width/height
337  Width = Height = (int)round_up_to_pow2((unsigned)std::max(g_Renderer.GetWidth(), g_Renderer.GetHeight()));
338  }
339  // Clamp to the maximum texture size
340  Width = std::min(Width, (int)ogl_max_tex_size);
341  Height = std::min(Height, (int)ogl_max_tex_size);
342 
343  // Since we're using a framebuffer object, the whole texture is available
346 
347  const char* formatname;
348 
349  switch(DepthTextureBits)
350  {
351  case 16: formatname = "DEPTH_COMPONENT16"; break;
352  case 24: formatname = "DEPTH_COMPONENT24"; break;
353  case 32: formatname = "DEPTH_COMPONENT32"; break;
354  default: formatname = "DEPTH_COMPONENT"; break;
355  }
356 
357  LOGMESSAGE(L"Creating shadow texture (size %dx%d) (format = %hs)",
358  Width, Height, formatname);
359 
360 
361  if (g_Renderer.m_Options.m_ShadowAlphaFix)
362  {
363  glGenTextures(1, &DummyTexture);
364  g_Renderer.BindTexture(0, DummyTexture);
365  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
366  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
367  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
368  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
369  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
370  }
371 
372  glGenTextures(1, &Texture);
373  g_Renderer.BindTexture(0, Texture);
374 
375  GLenum format;
376 
377 #if CONFIG2_GLES
378  format = GL_DEPTH_COMPONENT;
379 #else
380  switch (DepthTextureBits)
381  {
382  case 16: format = GL_DEPTH_COMPONENT16; break;
383  case 24: format = GL_DEPTH_COMPONENT24; break;
384  case 32: format = GL_DEPTH_COMPONENT32; break;
385  default: format = GL_DEPTH_COMPONENT; break;
386  }
387 #endif
388 
389  glTexImage2D(GL_TEXTURE_2D, 0, format, Width, Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
390  // GLES requires type == UNSIGNED_SHORT or UNSIGNED_INT
391 
392  // set texture parameters
393  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
394  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
395 
396 #if CONFIG2_GLES
397  // GLES doesn't do depth comparisons, so treat it as a
398  // basic unfiltered depth texture
399  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
400  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
401 #else
402  // Enable automatic depth comparisons
403  glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
404  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
405  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
406 
407  // Use GL_LINEAR to trigger automatic PCF on some devices
408  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
409  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
410 #endif
411 
412  ogl_WarnIfError();
413 
414  // bind to framebuffer object
415  glBindTexture(GL_TEXTURE_2D, 0);
416  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Framebuffer);
417 
418  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, Texture, 0);
419 
420  if (g_Renderer.m_Options.m_ShadowAlphaFix)
421  {
422  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, DummyTexture, 0);
423  }
424  else
425  {
426 #if CONFIG2_GLES
427 #warning TODO: figure out whether the glDrawBuffer/glReadBuffer stuff is needed, since it is not supported by GLES
428 #else
429  glDrawBuffer(GL_NONE);
430 #endif
431  }
432 
433 #if !CONFIG2_GLES
434  glReadBuffer(GL_NONE);
435 #endif
436 
437  ogl_WarnIfError();
438 
439  GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
440 
441  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, SavedViewFBO);
442 
443  if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
444  {
445  LOGWARNING(L"Framebuffer object incomplete: 0x%04X", status);
446 
447  // Disable shadow rendering (but let the user try again if they want)
448  g_Renderer.m_Options.m_Shadows = false;
449  }
450 }
451 
452 
453 ///////////////////////////////////////////////////////////////////////////////////////////////////
454 // Set up to render into shadow map texture
456 {
457  // HACK HACK: this depends in non-obvious ways on the behaviour of the caller
458 
459  // save caller's FBO
460  glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &m->SavedViewFBO);
461 
462  // Calc remaining shadow matrices
464 
465  {
466  PROFILE("bind framebuffer");
467  glBindTexture(GL_TEXTURE_2D, 0);
468  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m->Framebuffer);
469  }
470 
471  // clear buffers
472  {
473  PROFILE("clear depth texture");
474  // In case we used m_ShadowAlphaFix, we ought to clear the unused
475  // color buffer too, else Mali 400 drivers get confused.
476  // Might as well clear stencil too for completeness.
477  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
478  glColorMask(0,0,0,0);
479  }
480 
481  // setup viewport
482  glViewport(0, 0, m->EffectiveWidth, m->EffectiveHeight);
483 
484  m->SavedViewCamera = g_Renderer.GetViewCamera();
485 
489  g_Renderer.SetViewCamera(c);
490 
491 #if !CONFIG2_GLES
492  glMatrixMode(GL_PROJECTION);
493  glLoadMatrixf(&m->LightProjection._11);
494  glMatrixMode(GL_MODELVIEW);
495  glLoadMatrixf(&m->LightTransform._11);
496 #endif
497 
498  glEnable(GL_SCISSOR_TEST);
499  glScissor(1,1, m->EffectiveWidth-2, m->EffectiveHeight-2);
500 }
501 
502 
503 ///////////////////////////////////////////////////////////////////////////////////////////////////
504 // Finish rendering into shadow map texture
506 {
507  glDisable(GL_SCISSOR_TEST);
508 
509  g_Renderer.SetViewCamera(m->SavedViewCamera);
510 
511  {
512  PROFILE("unbind framebuffer");
513  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m->SavedViewFBO);
514  }
515 
516  glViewport(0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight());
517 
518  glColorMask(1,1,1,1);
519 }
520 
521 
522 ///////////////////////////////////////////////////////////////////////////////////////////////////
523 // Retrieve the texture handle and texture matrix for shadowing
524 GLuint ShadowMap::GetTexture() const
525 {
526  return m->Texture;
527 }
528 
530 {
531  return m->TextureMatrix;
532 }
533 
534 
535 ///////////////////////////////////////////////////////////////////////////////////////////////////
536 // Depth texture bits
538 {
539  return m->DepthTextureBits;
540 }
541 
543 {
544  if (bits != m->DepthTextureBits)
545  {
546  if (m->Texture)
547  {
548  glDeleteTextures(1, &m->Texture);
549  m->Texture = 0;
550  }
551  m->Width = m->Height = 0;
552 
554  }
555 }
556 
557 ///////////////////////////////////////////////////////////////////////////////////////////////////
558 // Depth texture size
560 {
561  return m->Width;
562 }
563 
565 {
566  return m->Height;
567 }
568 
569 //////////////////////////////////////////////////////////////////////////////
570 
572 {
573  CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid);
574  shaderTech->BeginPass();
575  CShaderProgramPtr shader = shaderTech->GetShader();
576 
577  glDepthMask(0);
578  glDisable(GL_CULL_FACE);
579 
580  // Render shadow bound
581  shader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection() * m->InvLightTransform);
582 
583  glEnable(GL_BLEND);
584  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
585  shader->Uniform(str_color, 0.0f, 0.0f, 1.0f, 0.25f);
586  m->ShadowBound.Render(shader);
587  glDisable(GL_BLEND);
588 
589  shader->Uniform(str_color, 0.0f, 0.0f, 1.0f, 1.0f);
590  m->ShadowBound.RenderOutline(shader);
591 
592  // Draw a funny line/triangle direction indicator thing for unknown reasons
593  float shadowLineVerts[] = {
594  0.0, 0.0, 0.0,
595  0.0, 0.0, 50.0,
596 
597  0.0, 0.0, 50.0,
598  50.0, 0.0, 50.0,
599 
600  50.0, 0.0, 50.0,
601  0.0, 50.0, 50.0,
602 
603  0.0, 50.0, 50.0,
604  0.0, 0.0, 50.0
605  };
606  shader->VertexPointer(3, GL_FLOAT, 0, shadowLineVerts);
607  shader->AssertPointersBound();
608  glDrawArrays(GL_LINES, 0, 8);
609 
610  shaderTech->EndPass();
611 
612 #if 0
613  CMatrix3D InvTexTransform;
614 
615  m->TextureMatrix.GetInverse(InvTexTransform);
616 
617  // Render representative texture rectangle
618  glPushMatrix();
619  glMultMatrixf(&InvTexTransform._11);
620 
621  glEnable(GL_BLEND);
622  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
623  glColor4ub(255,0,0,64);
624  glBegin(GL_QUADS);
625  glVertex3f(0.0, 0.0, 0.0);
626  glVertex3f(1.0, 0.0, 0.0);
627  glVertex3f(1.0, 1.0, 0.0);
628  glVertex3f(0.0, 1.0, 0.0);
629  glEnd();
630  glDisable(GL_BLEND);
631 
632  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
633  glColor3ub(255,0,0);
634  glBegin(GL_QUADS);
635  glVertex3f(0.0, 0.0, 0.0);
636  glVertex3f(1.0, 0.0, 0.0);
637  glVertex3f(1.0, 1.0, 0.0);
638  glVertex3f(0.0, 1.0, 0.0);
639  glEnd();
640  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
641  glPopMatrix();
642 #endif
643 
644  glEnable(GL_CULL_FACE);
645  glDepthMask(1);
646 }
647 
649 {
650  glDepthMask(0);
651 
652  glDisable(GL_DEPTH_TEST);
653 
654 #if !CONFIG2_GLES
655  g_Renderer.BindTexture(0, m->Texture);
656  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
657 #endif
658 
659  CShaderTechniquePtr texTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_basic);
660  texTech->BeginPass();
661  CShaderProgramPtr texShader = texTech->GetShader();
662 
663  texShader->Uniform(str_transform, GetDefaultGuiMatrix());
664  texShader->BindTexture(str_tex, m->Texture);
665 
666  float s = 256.f;
667  float boxVerts[] = {
668  0,0, 0,s, s,0,
669  s,0, 0,s, s,s
670  };
671  float boxUV[] = {
672  0,0, 0,1, 1,0,
673  1,0, 0,1, 1,1
674  };
675 
676  texShader->VertexPointer(2, GL_FLOAT, 0, boxVerts);
677  texShader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, boxUV);
678  texShader->AssertPointersBound();
679  glDrawArrays(GL_TRIANGLES, 0, 6);
680 
681  texTech->EndPass();
682 
683 #if !CONFIG2_GLES
684  g_Renderer.BindTexture(0, m->Texture);
685  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
686 #endif
687 
688  glEnable(GL_DEPTH_TEST);
689  glDepthMask(1);
690 }
GLint ogl_max_tex_size
Definition: ogl.cpp:468
float _21
Definition: Matrix3D.h:42
void Transform(const CMatrix3D &m, CBoundingBoxAligned &result) const
Transforms these bounds according to the specified transformation matrix m, and writes the axis-align...
Definition: Decompose.h:22
void RenderOutline(CShaderProgramPtr &shader) const
Render: Render the outline of the bound object as lines.
CMatrix3D GetDefaultGuiMatrix()
Definition: GUIutil.cpp:253
CCamera LightspaceCamera
Definition: ShadowMap.cpp:75
float _22
Definition: Matrix3D.h:43
float _12
Definition: Matrix3D.h:43
Definition: Decompose.h:22
void SetDepthTextureBits(int bits)
SetDepthTextureBits: Sets the number of bits to use for depth textures when enabled.
Definition: ShadowMap.cpp:542
int GetDepthTextureBits() const
GetDepthTextureBits: Return the number of bits to use for depth textures when enabled.
Definition: ShadowMap.cpp:537
void SetupFrame(const CCamera &camera, const CVector3D &lightdir)
SetupFrame: Configure light space for the given camera and light direction, create the shadow texture...
Definition: ShadowMap.cpp:153
float _44
Definition: Matrix3D.h:45
void AddShadowedBound(const CBoundingBoxAligned &bounds)
AddShadowedBound: Add the bounding box of an object that has to be shadowed.
Definition: ShadowMap.cpp:213
Struct ShadowMapInternals: Internal data for the ShadowMap implementation.
Definition: ShadowMap.cpp:47
#define LOGMESSAGE
Definition: CLogger.h:32
void SetZero()
Definition: Matrix3D.cpp:39
float Dot(const CVector3D &vector) const
Definition: Vector3D.cpp:48
float _43
Definition: Matrix3D.h:44
const CFrustum & GetFrustum() const
Definition: Camera.h:62
CVector3D Cross(const CVector3D &vector) const
Definition: Vector3D.cpp:55
GLuint GetTexture() const
GetTexture: Retrieve the OpenGL texture object name that contains the shadow map. ...
Definition: ShadowMap.cpp:524
shared_ptr< CShaderTechnique > CShaderTechniquePtr
void Normalize()
Definition: Vector3D.cpp:77
float _32
Definition: Matrix3D.h:43
float _11
Definition: Matrix3D.h:42
CCamera SavedViewCamera
Definition: ShadowMap.cpp:85
#define g_Renderer
Definition: Renderer.h:61
#define LOGWARNING
Definition: CLogger.h:34
CMatrix3D TextureMatrix
Definition: ShadowMap.cpp:67
float _33
Definition: Matrix3D.h:44
CVector3D GetIn() const
Definition: Matrix3D.cpp:253
int GetWidth() const
GetWidth: Return the width of the depth texture.
Definition: ShadowMap.cpp:559
T round_up_to_pow2(T x)
round up to next larger power of two.
Definition: bits.h:244
CMatrix3D & GetOrientation()
Definition: Camera.h:52
void CalcShadowMatrices()
Definition: ShadowMap.cpp:225
float X
Definition: Vector3D.h:31
void RenderDebugTexture()
Visualize shadow map texture to help in debugging.
Definition: ShadowMap.cpp:648
float Length() const
Definition: Vector3D.cpp:72
float Y
Definition: Vector3D.h:31
void IntersectFrustumConservative(const CFrustum &frustum)
IntersectFrustumConservative: Approximate the intersection of this bounds object with the given frust...
float _13
Definition: Matrix3D.h:44
CMatrix3D LightProjection
Definition: ShadowMap.cpp:62
Definition: Camera.h:39
float _31
Definition: Matrix3D.h:42
void SetIdentity()
Definition: Matrix3D.cpp:30
float _42
Definition: Matrix3D.h:43
#define PROFILE(name)
Definition: Profile.h:195
float _24
Definition: Matrix3D.h:45
T bits(T num, size_t lo_idx, size_t hi_idx)
extract the value of bits hi_idx:lo_idx within num
Definition: bits.h:97
float _34
Definition: Matrix3D.h:45
void BeginRender()
BeginRender: Set OpenGL state for rendering into the shadow map texture.
Definition: ShadowMap.cpp:455
const CMatrix3D & GetTextureMatrix() const
GetTextureMatrix: Retrieve the world-space to shadow map texture coordinates transformation matrix...
Definition: ShadowMap.cpp:529
void UpdateFrustum(const CBoundingBoxAligned &scissor=CBoundingBoxAligned(CVector3D(-1.0f,-1.0f,-1.0f), CVector3D(1.0f, 1.0f, 1.0f)))
Definition: Camera.cpp:83
void RenderDebugBounds()
Visualize shadow mapping calculations to help in debugging and optimal shadow map usage...
Definition: ShadowMap.cpp:571
float _23
Definition: Matrix3D.h:44
void GetInverse(CMatrix3D &dst) const
Definition: Matrix3D.cpp:277
void RecreateTexture()
RecreateTexture: Destroy the current shadow texture and force creation of a new one.
Definition: ShadowMap.cpp:135
CMatrix3D m_Orientation
Definition: Camera.h:112
float Z
Definition: Vector3D.h:31
CMatrix3D LightTransform
Definition: ShadowMap.cpp:64
void ogl_WarnIfError()
raise a warning (break into the debugger) if an OpenGL error is pending.
Definition: ogl.cpp:398
CBoundingBoxAligned ShadowBound
Definition: ShadowMap.cpp:72
CMatrix3D InvLightTransform
Definition: ShadowMap.cpp:70
ShadowMapInternals * m
Definition: ShadowMap.h:141
CVector3D GetTranslation() const
Definition: Matrix3D.cpp:195
void EndRender()
EndRender: Finish rendering into the shadow map.
Definition: ShadowMap.cpp:505
float _41
Definition: Matrix3D.h:42
void Render(CShaderProgramPtr &shader) const
Render: Render the surfaces of the bound object as triangles.
shared_ptr< CShaderProgram > CShaderProgramPtr
int GetHeight() const
GetHeight: Return the height of the depth texture.
Definition: ShadowMap.cpp:564
void SetProjection(float nearp, float farp, float fov)
Definition: Camera.cpp:51
float _14
Definition: Matrix3D.h:45