Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PostprocManager.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 "lib/ogl.h"
21 #include "maths/MathUtil.h"
22 
23 #include "gui/GUIutil.h"
24 #include "lib/bits.h"
25 #include "ps/CLogger.h"
26 #include "ps/Filesystem.h"
27 #include "ps/Game.h"
28 #include "ps/World.h"
29 
30 #include "graphics/GameView.h"
31 #include "graphics/LightEnv.h"
32 #include "graphics/ShaderManager.h"
33 
35 #include "renderer/Renderer.h"
36 
37 
39  : m_IsInitialised(false), m_PingFbo(0), m_PongFbo(0), m_PostProcEffect(L"default"), m_ColourTex1(0), m_ColourTex2(0),
40  m_DepthTex(0), m_BloomFbo(0), m_BlurTex2a(0), m_BlurTex2b(0), m_BlurTex4a(0), m_BlurTex4b(0),
41  m_BlurTex8a(0), m_BlurTex8b(0), m_WhichBuffer(true)
42 {
43 }
44 
46 {
47  Cleanup();
48 }
49 
50 
52 {
54  m_IsInitialised = true;
55  SetPostEffect(L"default");
56 }
57 
59 {
60  if (m_IsInitialised)
61  {
62  if (m_PingFbo) pglDeleteFramebuffersEXT(1, &m_PingFbo);
63  if (m_PongFbo) pglDeleteFramebuffersEXT(1, &m_PongFbo);
64  if (m_BloomFbo) pglDeleteFramebuffersEXT(1, &m_BloomFbo);
66 
67  if (m_ColourTex1) glDeleteTextures(1, &m_ColourTex1);
68  if (m_ColourTex2) glDeleteTextures(1, &m_ColourTex2);
69  if (m_DepthTex) glDeleteTextures(1, &m_DepthTex);
71 
72  if (m_BlurTex2a) glDeleteTextures(1, &m_BlurTex2a);
73  if (m_BlurTex2b) glDeleteTextures(1, &m_BlurTex2b);
74  if (m_BlurTex4a) glDeleteTextures(1, &m_BlurTex4a);
75  if (m_BlurTex4b) glDeleteTextures(1, &m_BlurTex4b);
76  if (m_BlurTex8a) glDeleteTextures(1, &m_BlurTex8a);
77  if (m_BlurTex8b) glDeleteTextures(1, &m_BlurTex8b);
79  }
80 }
81 
83 {
84  Cleanup();
85 
86  m_Width = g_Renderer.GetWidth();
87  m_Height = g_Renderer.GetHeight();
88 
89  #define GEN_BUFFER_RGBA(name, w, h) \
90  glGenTextures(1, (GLuint*)&name); \
91  glBindTexture(GL_TEXTURE_2D, name); \
92  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, \
93  GL_UNSIGNED_BYTE, 0); \
94  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); \
95  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); \
96  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); \
97  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
98 
99  // Two fullscreen ping-pong textures.
102 
103  // Textures for several blur sizes. It would be possible to reuse
104  // m_BlurTex2b, thus avoiding the need for m_BlurTex4b and m_BlurTex8b, though given
105  // that these are fairly small it's probably not worth complicating the coordinates passed
106  // to the blur helper functions.
109 
112 
115 
116  #undef GEN_BUFFER_RGBA
117 
118  // Allocate the Depth/Stencil texture.
119  glGenTextures(1, (GLuint*)&m_DepthTex);
120  glBindTexture(GL_TEXTURE_2D, m_DepthTex);
121  glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, m_Width, m_Height,
122  0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
123  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
124  GL_NONE);
125  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
126  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
127  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
128  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
129 
130  glBindTexture(GL_TEXTURE_2D, 0);
131 
132  // Set up the framebuffers with some initial textures.
133 
134  pglGenFramebuffersEXT(1, &m_PingFbo);
135  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
136  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_ColourTex1, 0);
137  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
138 
139  GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
140  if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
141  {
142  LOGWARNING(L"Framebuffer object incomplete (A): 0x%04X", status);
143  }
144 
145  pglGenFramebuffersEXT(1, &m_PongFbo);
146  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
147  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_ColourTex2, 0);
148  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
149 
150  status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
151  if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
152  {
153  LOGWARNING(L"Framebuffer object incomplete (B): 0x%04X", status);
154  }
155 
156  pglGenFramebuffersEXT(1, &m_BloomFbo);
157  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
158  /*pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_BloomTex1, 0);
159 
160  status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
161  if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
162  {
163  LOGWARNING(L"Framebuffer object incomplete (B): 0x%04X", status);
164  }*/
165 
166  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
167 }
168 
169 
170 void CPostprocManager::ApplyBlurDownscale2x(GLuint inTex, GLuint outTex, int inWidth, int inHeight)
171 {
172  // Bind inTex to framebuffer for rendering.
173  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
174  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, outTex, 0);
175 
176  // Get bloom shader with instructions to simply copy texels.
177  CShaderDefines defines;
178  defines.Add(str_BLOOM_NOP, str_1);
179  CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom,
180  g_Renderer.GetSystemShaderDefines(), defines);
181 
182  tech->BeginPass();
183  CShaderProgramPtr shader = tech->GetShader();
184 
185  GLuint renderedTex = inTex;
186 
187  // Cheat by creating high quality mipmaps for inTex, so the copying operation actually
188  // produces good scaling due to hardware filtering.
189  glBindTexture(GL_TEXTURE_2D, renderedTex);
190  pglGenerateMipmapEXT(GL_TEXTURE_2D);
191  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
192  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
193  glBindTexture(GL_TEXTURE_2D, 0);
194 
195  shader->BindTexture(str_renderedTex, renderedTex);
196 
197  glPushAttrib(GL_VIEWPORT_BIT);
198  glViewport(0, 0, inWidth / 2, inHeight / 2);
199 
200  glBegin(GL_QUADS);
201  glColor4f(1.f, 1.f, 1.f, 1.f);
202  glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
203  glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
204  glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
205  glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
206  glEnd();
207 
208  glPopAttrib();
209  tech->EndPass();
210 }
211 
212 void CPostprocManager::ApplyBlurGauss(GLuint inOutTex, GLuint tempTex, int inWidth, int inHeight)
213 {
214  // Set tempTex as our rendering target.
215  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
216  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tempTex, 0);
217 
218  // Get bloom shader, for a horizontal Gaussian blur pass.
219  CShaderDefines defines2;
220  defines2.Add(str_BLOOM_PASS_H, str_1);
221  CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom,
222  g_Renderer.GetSystemShaderDefines(), defines2);
223 
224  tech->BeginPass();
225  CShaderProgramPtr shader = tech->GetShader();
226  shader->BindTexture(str_renderedTex, inOutTex);
227  shader->Uniform(str_texSize, inWidth, inHeight, 0.0f, 0.0f);
228 
229  glPushAttrib(GL_VIEWPORT_BIT);
230  glViewport(0, 0, inWidth, inHeight);
231 
232  glBegin(GL_QUADS);
233  glColor4f(1.f, 1.f, 1.f, 1.f);
234  glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
235  glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
236  glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
237  glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
238  glEnd();
239 
240  glPopAttrib();
241  tech->EndPass();
242 
243  // Set result texture as our render target.
244  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_BloomFbo);
245  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, inOutTex, 0);
246 
247  // Get bloom shader, for a vertical Gaussian blur pass.
248  CShaderDefines defines3;
249  defines3.Add(str_BLOOM_PASS_V, str_1);
250  tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom,
251  g_Renderer.GetSystemShaderDefines(), defines3);
252 
253  tech->BeginPass();
254  shader = tech->GetShader();
255 
256  // Our input texture to the shader is the output of the horizontal pass.
257  shader->BindTexture(str_renderedTex, tempTex);
258  shader->Uniform(str_texSize, inWidth, inHeight, 0.0f, 0.0f);
259 
260  glPushAttrib(GL_VIEWPORT_BIT);
261  glViewport(0, 0, inWidth, inHeight);
262 
263  glBegin(GL_QUADS);
264  glColor4f(1.f, 1.f, 1.f, 1.f);
265  glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
266  glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
267  glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
268  glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
269  glEnd();
270 
271  glPopAttrib();
272  tech->EndPass();
273 }
274 
276 {
277  glDisable(GL_BLEND);
278 
279  GLint originalFBO;
280  glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &originalFBO);
281 
282  int width = m_Width, height = m_Height;
283 
284  #define SCALE_AND_BLUR(tex1, tex2, temptex) \
285  ApplyBlurDownscale2x(tex1, tex2, width, height); \
286  width /= 2; \
287  height /= 2; \
288  ApplyBlurGauss(tex2, temptex, width, height);
289 
290  // We do the same thing for each scale, incrementally adding more and more blur.
294 
295  #undef SCALE_AND_BLUR
296 
297  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, originalFBO);
298 }
299 
300 
302 {
303  // clear both FBOs and leave m_PingFbo selected for rendering;
304  // m_WhichBuffer stays true at this point
305  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
306  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
307 
308  GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
309  pglDrawBuffers(1, buffers);
310 
311  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
312  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
313  pglDrawBuffers(1, buffers);
314 
315  m_WhichBuffer = true;
316 }
317 
318 
320 {
321  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
322  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
323 
324  // we blit to screen from the previous active buffer
325  if (m_WhichBuffer)
326  pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_PingFbo);
327  else
328  pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_PongFbo);
329 
330  pglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
331  pglBlitFramebufferEXT(0, 0, m_Width, m_Height, 0, 0, m_Width, m_Height,
332  GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
333  pglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
334 
335  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
336 }
337 
338 
340 {
341  if (!m_IsInitialised)
342  return;
343 
344  if (name != L"default")
345  {
346  CStrW n = L"postproc/" + name;
347  m_PostProcTech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern(n.ToUTF8()));
348  }
349 
350  m_PostProcEffect = name;
351 }
352 
353 
355 {
356  // select the other FBO for rendering
357  if (!m_WhichBuffer)
358  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
359  else
360  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
361 
362  glDisable(GL_DEPTH_TEST);
363  glDepthMask(GL_FALSE);
364 
365  shaderTech1->BeginPass(pass);
366  CShaderProgramPtr shader = shaderTech1->GetShader(pass);
367 
368  shader->Bind();
369 
370  // Use the textures from the current FBO as input to the shader.
371  // We also bind a bunch of other textures and parameters, but since
372  // this only happens once per frame the overhead is negligible.
373  if (m_WhichBuffer)
374  shader->BindTexture(str_renderedTex, m_ColourTex1);
375  else
376  shader->BindTexture(str_renderedTex, m_ColourTex2);
377 
378  shader->BindTexture(str_depthTex, m_DepthTex);
379 
380  shader->BindTexture(str_blurTex2, m_BlurTex2a);
381  shader->BindTexture(str_blurTex4, m_BlurTex4a);
382  shader->BindTexture(str_blurTex8, m_BlurTex8a);
383 
384  shader->Uniform(str_width, m_Width);
385  shader->Uniform(str_height, m_Height);
386  shader->Uniform(str_zNear, g_Game->GetView()->GetNear());
387  shader->Uniform(str_zFar, g_Game->GetView()->GetFar());
388 
389  shader->Uniform(str_brightness, g_LightEnv.m_Brightness);
390  shader->Uniform(str_hdr, g_LightEnv.m_Contrast);
391  shader->Uniform(str_saturation, g_LightEnv.m_Saturation);
392  shader->Uniform(str_bloom, g_LightEnv.m_Bloom);
393 
394  glBegin(GL_QUADS);
395  glColor4f(1.f, 1.f, 1.f, 1.f);
396  glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
397  glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
398  glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
399  glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
400  glEnd();
401 
402  shader->Unbind();
403 
404  shaderTech1->EndPass(pass);
405 
406  glDepthMask(GL_TRUE);
407  glEnable(GL_DEPTH_TEST);
408 
410 }
411 
413 {
414  if (!m_IsInitialised)
415  return;
416 
417  // Don't do anything if we are using the default effect.
418  if (m_PostProcEffect == L"default")
419  {
420  return;
421  }
422 
423  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
424  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, 0, 0);
425 
426  GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT };
427  pglDrawBuffers(1, buffers);
428 
429  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
430  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, 0, 0);
431  pglDrawBuffers(1, buffers);
432 
433  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
434  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
435 
436  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
437  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
438 
439  // First render blur textures. Note that this only happens ONLY ONCE, before any effects are applied!
440  // (This may need to change depending on future usage, however that will have a fps hit)
441  ApplyBlur();
442 
443  for (int pass = 0; pass < m_PostProcTech->GetNumPasses(); ++pass)
444  {
446  }
447 
448  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
449  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
450 
451  pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
452  pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
453 }
454 
455 
456 // Generate list of available effect-sets
457 std::vector<CStrW> CPostprocManager::GetPostEffects() const
458 {
459  std::vector<CStrW> effects;
460 
461  const VfsPath path(L"shaders/effects/postproc/");
462 
463  VfsPaths pathnames;
464  if(vfs::GetPathnames(g_VFS, path, 0, pathnames) < 0)
465  {
466  LOGERROR(L"Error finding Post effects in '%ls'", path.string().c_str());
467  }
468 
469  for(size_t i = 0; i < pathnames.size(); i++)
470  {
471  if (pathnames[i].Extension() != L".xml")
472  continue;
473 
474  effects.push_back(pathnames[i].Basename().string());
475  }
476 
477  // Add the default "null" effect to the list.
478  effects.push_back(L"default");
479 
480  sort(effects.begin(), effects.end());
481 
482  return effects;
483 }
484 
486 {
487  LoadEffect(name);
488 }
void Add(CStrIntern name, CStrIntern value)
Add a name and associated value to the map of defines.
float GetFar() const
Definition: GameView.cpp:1046
CShaderTechniquePtr m_PostProcTech
#define LOGERROR
Definition: CLogger.h:35
CLightEnv g_LightEnv
File : World.cpp Project : engine Description : Contains the CWorld Class implementation.
Definition: World.cpp:49
void ApplyBlurGauss(GLuint inOutTex, GLuint tempTex, int inWidth, int inHeight)
shared_ptr< CShaderTechnique > CShaderTechniquePtr
std::vector< CStrW > GetPostEffects() const
#define g_Renderer
Definition: Renderer.h:61
#define LOGWARNING
Definition: CLogger.h:34
#define GEN_BUFFER_RGBA(name, w, h)
Interned 8-bit strings.
Definition: CStrIntern.h:37
void ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass)
Definition: path.h:75
const String & string() const
Definition: path.h:123
float m_Bloom
Definition: LightEnv.h:77
CGame * g_Game
Globally accessible pointer to the CGame object.
Definition: Game.cpp:56
float m_Contrast
Definition: LightEnv.h:77
Represents a mapping of name strings to value strings, for use with #if and #ifdef and similar condit...
CGameView * GetView()
Get the pointer to the game view object.
Definition: Game.h:128
float GetNear() const
Definition: GameView.cpp:1041
float m_Saturation
Definition: LightEnv.h:77
std::vector< VfsPath > VfsPaths
Definition: vfs_path.h:42
float m_Brightness
Definition: LightEnv.h:77
void ApplyBlurDownscale2x(GLuint inTex, GLuint outTex, int inWidth, int inHeight)
PIVFS g_VFS
Definition: Filesystem.cpp:30
shared_ptr< CShaderProgram > CShaderProgramPtr
Status GetPathnames(const PIVFS &fs, const VfsPath &path, const wchar_t *filter, VfsPaths &pathnames)
Definition: vfs_util.cpp:40
#define SCALE_AND_BLUR(tex1, tex2, temptex)
void LoadEffect(CStrW &name)
void SetPostEffect(CStrW name)