FS2_Open
Open source remastering of the Freespace 2 engine
gropenglpostprocessing.cpp
Go to the documentation of this file.
1 
2 #include "cmdline/cmdline.h"
3 #include "freespace2/freespace.h"
4 #include "globalincs/def_files.h"
5 #include "graphics/gropengl.h"
10 #include "graphics/gropenglstate.h"
11 #include "io/timer.h"
12 #include "lighting/lighting.h"
13 #include "mod_table/mod_table.h"
14 #include "nebula/neb.h"
15 #include "parse/parselo.h"
16 #include "ship/ship.h"
17 
18 
19 extern bool PostProcessing_override;
20 extern int opengl_check_framebuffer();
21 
22 //Needed to track where the FXAA shaders are
24 //In case we don't find the shaders at all, this override is needed
25 bool fxaa_unavailable = false;
27 bool zbuffer_saved = false;
28 
29 // lightshaft parameters
30 bool ls_on = false;
31 bool ls_force_off = false;
32 float ls_density = 0.5f;
33 float ls_weight = 0.02f;
34 float ls_falloff = 1.0f;
35 float ls_intensity = 0.5f;
36 float ls_cpintensity = 0.5f * 50 * 0.02f;
37 int ls_samplenum = 50;
38 
39 typedef struct post_effect_t {
43 
44  float intensity;
46  float div;
47  float add;
48 
49  bool always_on;
50 
52  intensity(0.0f), default_intensity(0.0f), div(1.0f), add(0.0f),
53  always_on(false)
54  {
55  }
57 
59 
60 static int Post_initialized = 0;
61 
62 bool Post_in_frame = false;
63 
64 static int Post_active_shader_index = -1;
65 
66 static GLuint Post_framebuffer_id[2] = { 0 };
67 static GLuint Post_bloom_texture_id[3] = { 0 };
68 static GLuint Post_shadow_framebuffer_id = 0;
69 static GLuint Post_shadow_texture_id = 0;
70 static GLuint Post_shadow_depth_texture_id = 0;
71 
72 static int Post_texture_width = 0;
73 static int Post_texture_height = 0;
74 
75 static bool opengl_post_pass_bloom()
76 {
77  if (Cmdline_bloom_intensity <= 0) {
78  return false;
79  }
80 
81  // we need the scissor test disabled
82  GLboolean scissor_test = GL_state.ScissorTest(GL_FALSE);
83 
84  // ------ begin bright pass ------
85 
86  vglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Post_framebuffer_id[0]);
87 
88  // width and height are 1/2 for the bright pass
89  int width = Post_texture_width >> 1;
90  int height = Post_texture_height >> 1;
91 
92  glViewport(0, 0, width, height);
93 
94  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
96 
98 
99  GL_state.Uniform.setUniformi( "tex", 0 );
100 
104 
105  opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f);
106 
108 
109  // ------ end bright pass ------
110 
111 
112  // ------ begin blur pass ------
113 
116 
117  // drop width and height once more for the blur passes
118  width >>= 1;
119  height >>= 1;
120 
121  glViewport(0, 0, width, height);
122 
123  vglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Post_framebuffer_id[1]);
124 
125  for (int pass = 0; pass < 2; pass++) {
127 
128  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
130 
131  if ( pass ) {
133  } else {
135  }
136 
137  GL_state.Uniform.setUniformi( "tex", 0 );
138  GL_state.Uniform.setUniformf( "bsize", (pass) ? (float)width : (float)height );
139 
140  GL_state.Texture.Enable(Post_bloom_texture_id[pass]);
141 
142  opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f);
143  }
144 
146 
147  // ------ end blur pass --------
148 
149  // reset viewport, scissor test and exit
151  GL_state.ScissorTest(scissor_test);
152 
154 
155  return true;
156 }
157 
159 {
160  if ( !Post_initialized ) {
161  return;
162  }
163 
164  if (Post_in_frame) {
165  return;
166  }
167 
169  return;
170  }
171 
172  vglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Post_framebuffer_id[0]);
173 
174 // vglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, Post_renderbuffer_id);
175 
176 // vglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Post_screen_texture_id, 0);
177 
178 // Assert( !opengl_check_framebuffer() );
179 
181 
182  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
184 
185  Post_in_frame = true;
186 }
187 
189 
190  mprintf(("Recompiling FXAA shader with preset %d\n", Cmdline_fxaa_preset));
191 
192  // start recompile by grabbing deleting the current shader we have, assuming it's already created
194 
195  // then recreate it again. shader loading code will be updated with the new FXAA presets
197 
199 }
200 
202 
203  //If the preset changed, recompile the shader
206  }
207 
208  // We only want to draw to ATTACHMENT0
210 
211  // Do a prepass to convert the main shaders' RGBA output into RGBL
213 
214  // basic/default uniforms
215  GL_state.Uniform.setUniformi( "tex", 0 );
216 
218 
222 
224 
226 
227  // set and configure post shader ..
229 
231 
232  // basic/default uniforms
233  GL_state.Uniform.setUniformi( "tex0", 0 );
234  GL_state.Uniform.setUniformf( "rt_w", static_cast<float>(Post_texture_width));
235  GL_state.Uniform.setUniformf( "rt_h", static_cast<float>(Post_texture_height));
236 
240 
242 
244 
246 }
247 
254 extern bool stars_sun_has_glare(int index);
255 extern float Sun_spot;
257 {
258  // state switch just the once (for bloom pass and final render-to-screen)
260  GLboolean depth_mask = GL_state.DepthMask(GL_FALSE);
261  GLboolean lighting = GL_state.Lighting(GL_FALSE);
262  GLboolean blend = GL_state.Blend(GL_FALSE);
264 
266 
267  // Do FXAA
270  }
271 
273  float x,y;
274  // should we even be here?
276  {
277  int n_lights = light_get_global_count();
278 
279  for(int idx=0; idx<n_lights; idx++)
280  {
281  vec3d light_dir;
282  vec3d local_light_dir;
283  light_get_global_dir(&light_dir, idx);
284  vm_vec_rotate(&local_light_dir, &light_dir, &Eye_matrix);
285  if (!stars_sun_has_glare(idx))
286  continue;
287  float dot;
288  if((dot=vm_vec_dot( &light_dir, &Eye_matrix.vec.fvec )) > 0.7f)
289  {
290 
291  x = asinf(vm_vec_dot( &light_dir, &Eye_matrix.vec.rvec ))/PI*1.5f+0.5f; //cant get the coordinates right but this works for the limited glare fov
292  y = asinf(vm_vec_dot( &light_dir, &Eye_matrix.vec.uvec ))/PI*1.5f*gr_screen.clip_aspect+0.5f;
293  GL_state.Uniform.setUniform2f( "sun_pos", x, y);
294  GL_state.Uniform.setUniformi( "scene", 0);
295  GL_state.Uniform.setUniformi( "cockpit", 1);
296  GL_state.Uniform.setUniformf( "density", ls_density);
297  GL_state.Uniform.setUniformf( "falloff", ls_falloff);
299  GL_state.Uniform.setUniformf( "intensity", Sun_spot * ls_intensity);
300  GL_state.Uniform.setUniformf( "cp_intensity", Sun_spot * ls_cpintensity);
301 
304  GL_state.Texture.Enable(Scene_depth_texture);
307  GL_state.Texture.Enable(Cockpit_depth_texture);
308  GL_state.Color(255, 255, 255, 255);
311 
313 
315  break;
316  }
317  }
318  }
319  if(zbuffer_saved)
320  {
321  zbuffer_saved = false;
326  }
327 
328  // Bind the correct framebuffer. opengl_get_rtt_framebuffer returns 0 if not doing RTT
330 
331  // do bloom, hopefully ;)
332  bool bloomed = opengl_post_pass_bloom();
333 
334  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
336 
337  GL_state.Color(255, 255, 255, 255);
338 
339  // set and configure post shader ...
340  int flags = 0;
341  for ( int i = 0; i < (int)Post_effects.size(); i++) {
342  if (Post_effects[i].always_on) {
343  flags |= (1 << i);
344  }
345  }
346 
347  int post_sdr_handle = Post_active_shader_index;
348 
349  if ( post_sdr_handle < 0 ) {
350  // no active shader index? use the always on shader.
352  }
353 
354  opengl_shader_set_current(post_sdr_handle);
355 
356  // basic/default uniforms
357  GL_state.Uniform.setUniformi( "tex", 0 );
358  GL_state.Uniform.setUniformi( "depth_tex", 2);
359  GL_state.Uniform.setUniformf( "timer", static_cast<float>(timer_get_milliseconds() % 100 + 1) );
360 
361  for (size_t idx = 0; idx < Post_effects.size(); idx++) {
362  if ( GL_shader[post_sdr_handle].flags & (1<<idx) ) {
363  const char *name = Post_effects[idx].uniform_name.c_str();
364  float value = Post_effects[idx].intensity;
365 
366  GL_state.Uniform.setUniformf( name, value);
367  }
368  }
369 
370  // bloom uniforms, but only if we did the bloom
371  if (bloomed) {
372  float intensity = MIN((float)Cmdline_bloom_intensity, 200.0f) * 0.01f;
373 
375  // we need less intensity for full neb missions, so cut it by 30%
376  intensity /= 3.0f;
377  }
378 
379  GL_state.Uniform.setUniformf( "bloom_intensity", intensity );
380 
381  GL_state.Uniform.setUniformi( "bloomed", 1 );
382 
385  GL_state.Texture.Enable(Post_bloom_texture_id[2]);
386  }
387  else
388  GL_state.Uniform.setUniformf( "bloom_intensity", 0.0f );
389 
390  // now render it to the screen ...
395 
398  GL_state.Texture.Enable(Scene_depth_texture);
399 
401 
402  //Shadow Map debug window
403 //#define SHADOW_DEBUG
404 #ifdef SHADOW_DEBUG
405  opengl_shader_set_current( &GL_post_shader[7] );
407 // GL_state.Texture.SetTarget(GL_TEXTURE_2D);
409 // GL_state.Texture.Enable(Shadow_map_depth_texture);
410  extern GLuint Shadow_map_texture;
411  extern GLuint Post_shadow_texture_id;
412  GL_state.Texture.Enable(Shadow_map_texture);
413  vglUniform1iARB( opengl_shader_get_uniform("shadow_map"), 0);
415  //opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, Scene_texture_u_scale, Scene_texture_u_scale);
416  //opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.5f);
417  opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 1.0f, 1.0f);
419  //opengl_draw_textured_quad(-1.0f, -0.5f, 0.5f, 0.0f, -0.5f, 0.0f, 0.75f, 0.25f);
420  opengl_draw_textured_quad(-1.0f, -0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 1.0f);
422  opengl_draw_textured_quad(-0.5f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 1.0f, 1.0f);
424  opengl_draw_textured_quad(-0.5f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 1.0f, 1.0f);
426 #endif
427 
428  /*GL_state.Texture.SetActiveUnit(0);
429  GL_state.Texture.SetTarget(GL_TEXTURE_2D);
430  GL_state.Texture.Enable(Scene_depth_texture);
431 
432 
433  */
434  // Done!
435  /*GL_state.Texture.SetActiveUnit(0);
436  GL_state.Texture.SetTarget(GL_TEXTURE_2D);
437  GL_state.Texture.Enable(Scene_effect_texture);
438 
439  opengl_draw_textured_quad(0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale);
440 
441  GL_state.Texture.SetActiveUnit(0);
442  GL_state.Texture.SetTarget(GL_TEXTURE_2D);
443  GL_state.Texture.Enable(Scene_normal_texture);
444 
445  opengl_draw_textured_quad(-1.0f, -0.0f, 0.0f, 0.0f, 0.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale);
446 
447  GL_state.Texture.SetActiveUnit(0);
448  GL_state.Texture.SetTarget(GL_TEXTURE_2D);
449  GL_state.Texture.Enable(Scene_specular_texture);
450 
451  opengl_draw_textured_quad(0.0f, -0.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale);
452  */
459 
461 
462  // reset state
463  GL_state.DepthTest(depth);
464  GL_state.DepthMask(depth_mask);
465  GL_state.Lighting(lighting);
466  GL_state.Blend(blend);
467  GL_state.CullFace(cull);
468 
470 
471  Post_in_frame = false;
472 }
473 
475 {
476  size_t idx;
477 
478  for (idx = 0; idx < Post_effects.size(); idx++) {
479  names.push_back(Post_effects[idx].name);
480  }
481 }
482 
484 {
485  for (int idx = 0; idx < (int)Post_effects.size(); idx++) {
486  if (flags & (1 << idx)) {
487  opengl_shader_init_uniform(Post_effects[idx].uniform_name.c_str());
488  }
489  }
490 }
491 
493 {
494  if ( !Post_initialized ) {
495  return;
496  }
497 
498  if (name == NULL) {
499  return;
500  }
501 
502  size_t idx;
503  int sflags = 0;
504 
505  if(!stricmp("lightshafts",name))
506  {
507  ls_intensity = value / 100.0f;
508  ls_on = !!value;
509  return;
510  }
511 
512  for (idx = 0; idx < Post_effects.size(); idx++) {
513  const char *eff_name = Post_effects[idx].name.c_str();
514 
515  if ( !stricmp(eff_name, name) ) {
516  Post_effects[idx].intensity = (value / Post_effects[idx].div) + Post_effects[idx].add;
517  break;
518  }
519  }
520 
521  // figure out new flags
522  for (idx = 0; idx < Post_effects.size(); idx++) {
523  if ( Post_effects[idx].always_on || (Post_effects[idx].intensity != Post_effects[idx].default_intensity) ) {
524  sflags |= (1<<idx);
525  }
526  }
527 
528  Post_active_shader_index = gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_MAIN, sflags);
529 }
530 
532 {
533  size_t idx;
534 
535  if ( !Post_initialized ) {
536  return;
537  }
538 
539  // reset all effects to their default values
540  for (idx = 0; idx < Post_effects.size(); idx++) {
541  Post_effects[idx].intensity = Post_effects[idx].default_intensity;
542  }
543 
544  Post_active_shader_index = -1;
545 }
546 
549 {
550  if (Post_initialized)
551  {
554  zbuffer_saved = true;
555  }
556  else
557  {
558  // If we can't save the z-buffer then just clear it so cockpits are still rendered correctly when
559  // post-processing isn't available/enabled.
561  }
562 }
563 
564 
565 static bool opengl_post_init_table()
566 {
567  bool warned = false;
568 
569  try
570  {
571  if (cf_exists_full("post_processing.tbl", CF_TYPE_TABLES))
572  read_file_text("post_processing.tbl", CF_TYPE_TABLES);
573  else
574  read_file_text_from_array(defaults_get_file("post_processing.tbl"));
575 
576  reset_parse();
577 
578 
579  if (optional_string("#Effects")) {
580  while (!required_string_one_of(3, "$Name:", "#Ship Effects", "#End")) {
581  char tbuf[NAME_LENGTH + 1] = { 0 };
582  post_effect_t eff;
583 
584  required_string("$Name:");
586  eff.name = tbuf;
587 
588  required_string("$Uniform:");
590  eff.uniform_name = tbuf;
591 
592  required_string("$Define:");
594  eff.define_name = tbuf;
595 
596  required_string("$AlwaysOn:");
597  stuff_boolean(&eff.always_on);
598 
599  required_string("$Default:");
601  eff.intensity = eff.default_intensity;
602 
603  required_string("$Div:");
604  stuff_float(&eff.div);
605 
606  required_string("$Add:");
607  stuff_float(&eff.add);
608 
609  // Post_effects index is used for flag checks, so we can't have more than 32
610  if (Post_effects.size() < 32) {
611  Post_effects.push_back(eff);
612  }
613  else if (!warned) {
614  mprintf(("WARNING: post_processing.tbl can only have a max of 32 effects! Ignoring extra...\n"));
615  warned = true;
616  }
617  }
618  }
619 
620  //Built-in per-ship effects
621  ship_effect se1;
622  strcpy_s(se1.name, "FS1 Ship select");
623  se1.shader_effect = 0;
624  se1.disables_rendering = false;
625  se1.invert_timer = false;
626  Ship_effects.push_back(se1);
627 
628  if (optional_string("#Ship Effects")) {
629  while (!required_string_one_of(3, "$Name:", "#Light Shafts", "#End")) {
630  ship_effect se;
631  char tbuf[NAME_LENGTH] = { 0 };
632 
633  required_string("$Name:");
635  strcpy_s(se.name, tbuf);
636 
637  required_string("$Shader Effect:");
639 
640  required_string("$Disables Rendering:");
642 
643  required_string("$Invert timer:");
645 
646  Ship_effects.push_back(se);
647  }
648  }
649 
650  if (optional_string("#Light Shafts")) {
651  required_string("$AlwaysOn:");
653  required_string("$Density:");
655  required_string("$Falloff:");
657  required_string("$Weight:");
659  required_string("$Intensity:");
661  required_string("$Sample Number:");
663 
665  for (int i = 1; i < ls_samplenum; i++)
668  }
669 
670  required_string("#End");
671 
672  return true;
673  }
674  catch (const parse::ParseException& e)
675  {
676  mprintf(("Unable to parse 'post_processing.tbl'! Error message = %s.\n", e.what()));
677  return false;
678  }
679 }
680 
682 {
683  if ( shader_t == SDR_TYPE_POST_PROCESS_MAIN ) {
684  for (size_t idx = 0; idx < Post_effects.size(); idx++) {
685  if (flags & (1 << idx)) {
686  sflags << "#define ";
687  sflags << Post_effects[idx].define_name.c_str();
688  sflags << "\n";
689  }
690  }
691  } else if ( shader_t == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS ) {
692  char temp[64];
693  sprintf(temp, "#define SAMPLE_NUM %d\n", ls_samplenum);
694  sflags << temp;
695  } else if ( shader_t == SDR_TYPE_POST_PROCESS_FXAA ) {
696  /* GLSL version < 120 are guarded against reaching this code
697  path via testing is_minimum_GLSL_version().
698  Accordingly do not test for them again here. */
699  if (GLSL_version == 120) {
700  sflags << "#define FXAA_GLSL_120 1\n";
701  sflags << "#define FXAA_GLSL_130 0\n";
702  }
703  if (GLSL_version > 120) {
704  sflags << "#define FXAA_GLSL_120 0\n";
705  sflags << "#define FXAA_GLSL_130 1\n";
706  }
707 
708  switch (Cmdline_fxaa_preset) {
709  case 0:
710  sflags << "#define FXAA_QUALITY_PRESET 10\n";
711  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/6.0)\n";
712  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/12.0)\n";
713  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
714  break;
715  case 1:
716  sflags << "#define FXAA_QUALITY_PRESET 11\n";
717  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/7.0)\n";
718  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/14.0)\n";
719  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
720  break;
721  case 2:
722  sflags << "#define FXAA_QUALITY_PRESET 12\n";
723  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/8.0)\n";
724  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/16.0)\n";
725  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
726  break;
727  case 3:
728  sflags << "#define FXAA_QUALITY_PRESET 13\n";
729  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/9.0)\n";
730  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/18.0)\n";
731  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
732  break;
733  case 4:
734  sflags << "#define FXAA_QUALITY_PRESET 14\n";
735  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/10.0)\n";
736  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/20.0)\n";
737  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
738  break;
739  case 5:
740  sflags << "#define FXAA_QUALITY_PRESET 25\n";
741  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/11.0)\n";
742  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/22.0)\n";
743  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
744  break;
745  case 6:
746  sflags << "#define FXAA_QUALITY_PRESET 26\n";
747  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/12.0)\n";
748  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/24.0)\n";
749  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
750  break;
751  case 7:
752  sflags << "#define FXAA_PC 1\n";
753  sflags << "#define FXAA_QUALITY_PRESET 27\n";
754  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/13.0)\n";
755  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/26.0)\n";
756  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
757  break;
758  case 8:
759  sflags << "#define FXAA_QUALITY_PRESET 28\n";
760  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/14.0)\n";
761  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/28.0)\n";
762  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
763  break;
764  case 9:
765  sflags << "#define FXAA_QUALITY_PRESET 39\n";
766  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/15.0)\n";
767  sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/32.0)\n";
768  sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
769  break;
770  }
771  }
772 }
773 
775 {
776  int idx;
777  int flags = 0;
778 
779  // figure out which flags we need for the main post process shader
780  for (idx = 0; idx < (int)Post_effects.size(); idx++) {
781  if (Post_effects[idx].always_on) {
782  flags |= (1 << idx);
783  }
784  }
785 
787  // only the main shader is actually required for post-processing
788  return false;
789  }
790 
794  // disable bloom if we don't have those shaders available
796  }
797 
800  Cmdline_fxaa = false;
801  fxaa_unavailable = true;
802  mprintf(("Error while compiling FXAA shaders. FXAA will be unavailable.\n"));
803  }
804 
805  return true;
806 }
807 
808 // generate and test the framebuffer and textures that we are going to use
809 static bool opengl_post_init_framebuffer()
810 {
811  bool rval = false;
812 
813  // clamp size, if needed
814  Post_texture_width = gr_screen.max_w;
815  Post_texture_height = gr_screen.max_h;
816 
817  if (Post_texture_width > GL_max_renderbuffer_size) {
818  Post_texture_width = GL_max_renderbuffer_size;
819  }
820 
821  if (Post_texture_height > GL_max_renderbuffer_size) {
822  Post_texture_height = GL_max_renderbuffer_size;
823  }
824 
825  if (Cmdline_bloom_intensity > 0) {
826  // two more framebuffers, one each for the two different sized bloom textures
827  vglGenFramebuffersEXT(1, &Post_framebuffer_id[0]);
828  vglGenFramebuffersEXT(1, &Post_framebuffer_id[1]);
829 
830  // need to generate textures for bloom too
831  glGenTextures(3, Post_bloom_texture_id);
832 
833  // half size
834  int width = Post_texture_width >> 1;
835  int height = Post_texture_height >> 1;
836 
837  for (int tex = 0; tex < 3; tex++) {
840  GL_state.Texture.Enable(Post_bloom_texture_id[tex]);
841 
847 
849 
850  if (tex == 0) {
851  // attach to our bright pass framebuffer and make sure it's ok
852  vglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Post_framebuffer_id[0]);
854 
855  // if not then clean up and disable bloom
856  if ( opengl_check_framebuffer() ) {
858  vglDeleteFramebuffersEXT(1, &Post_framebuffer_id[0]);
859  vglDeleteFramebuffersEXT(1, &Post_framebuffer_id[1]);
860  Post_framebuffer_id[0] = 0;
861  Post_framebuffer_id[1] = 0;
862 
863  glDeleteTextures(3, Post_bloom_texture_id);
864  memset(Post_bloom_texture_id, 0, sizeof(Post_bloom_texture_id));
865 
867 
868  break;
869  }
870 
871  // width and height are 1/2 for the bright pass, 1/4 for the blur, so drop down
872  width >>= 1;
873  height >>= 1;
874  } else {
875  // attach to our blur pass framebuffer and make sure it's ok
876  vglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Post_framebuffer_id[1]);
878 
879  // if not then clean up and disable bloom
880  if ( opengl_check_framebuffer() ) {
882  vglDeleteFramebuffersEXT(1, &Post_framebuffer_id[0]);
883  vglDeleteFramebuffersEXT(1, &Post_framebuffer_id[1]);
884  Post_framebuffer_id[0] = 0;
885  Post_framebuffer_id[1] = 0;
886 
887  glDeleteTextures(3, Post_bloom_texture_id);
888  memset(Post_bloom_texture_id, 0, sizeof(Post_bloom_texture_id));
889 
891 
892  break;
893  }
894  }
895  }
896  }
897 
898  if ( Cmdline_shadow_quality ) {
899  int size = (Cmdline_shadow_quality == 2 ? 1024 : 512);
900 
901  vglGenFramebuffersEXT(1, &Post_shadow_framebuffer_id);
902  vglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, Post_shadow_framebuffer_id);
903 
904  glGenTextures(1, &Post_shadow_texture_id);
905 
908 // GL_state.Texture.SetTarget(GL_TEXTURE_2D);
909  GL_state.Texture.Enable(Post_shadow_texture_id);
910 
917 
918 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
919 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
920 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
921 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
922 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
923 // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, size, size, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
924 
925 // vglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Post_shadow_texture_id, 0);
927 
928  glGenTextures(1, &Post_shadow_depth_texture_id);
929 
932 // GL_state.Texture.SetTarget(GL_TEXTURE_2D);
933  GL_state.Texture.Enable(Post_shadow_depth_texture_id);
934 
941 
942 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
943 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
944 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
945 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
946 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
947 // glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, size, size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
948 
949 // vglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, Post_shadow_depth_texture_id, 0);
950  vglFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, Post_shadow_depth_texture_id, 0);
951  }
952 
954 
956 
957  rval = true;
958 
959  if ( opengl_check_for_errors("post_init_framebuffer()") ) {
960  rval = false;
961  }
962 
963  return rval;
964 }
965 
967 {
968  Post_initialized = 0;
969 
970  //We need to read the tbl first. This is mostly for FRED's benefit, as otherwise the list of post effects for the sexp doesn't get updated.
971  if ( !opengl_post_init_table() ) {
972  mprintf((" Unable to read post-processing table! Disabling post-processing...\n\n"));
974  return;
975  }
976 
977  if ( !Cmdline_postprocess ) {
978  return;
979  }
980 
981  if ( !Scene_texture_initialized ) {
982  return;
983  }
984 
987  return;
988  }
989 
990  // for ease of use we require support for non-power-of-2 textures in one
991  // form or another:
992  // - the NPOT extension
993  // - GL version 2.0+ (which should work for non-reporting ATI cards since we don't use mipmaps)
996  return;
997  }
998 
999  if ( !opengl_post_init_shaders() ) {
1000  mprintf((" Unable to initialize post-processing shaders! Disabling post-processing...\n\n"));
1001  Cmdline_postprocess = 0;
1002  return;
1003  }
1004 
1005  if ( !opengl_post_init_framebuffer() ) {
1006  mprintf((" Unable to initialize post-processing framebuffer! Disabling post-processing...\n\n"));
1007  Cmdline_postprocess = 0;
1008  return;
1009  }
1010 
1011  Post_initialized = 1;
1012 }
1013 
1015 {
1016  if ( !Post_initialized ) {
1017  return;
1018  }
1019 
1020  if (Post_bloom_texture_id[0]) {
1021  glDeleteTextures(3, Post_bloom_texture_id);
1022  memset(Post_bloom_texture_id, 0, sizeof(Post_bloom_texture_id));
1023  }
1024 
1025  if (Post_framebuffer_id[0]) {
1026  vglDeleteFramebuffersEXT(1, &Post_framebuffer_id[0]);
1027  Post_framebuffer_id[0] = 0;
1028 
1029  if (Post_framebuffer_id[1]) {
1030  vglDeleteFramebuffersEXT(1, &Post_framebuffer_id[1]);
1031  Post_framebuffer_id[1] = 0;
1032  }
1033  }
1034 
1035  Post_effects.clear();
1036 
1037  Post_in_frame = false;
1038  Post_active_shader_index = 0;
1039 
1040  Post_initialized = 0;
1041 }
unsigned int GLuint
Definition: Gl.h:52
GLuint Cockpit_depth_texture
#define gr_zbuffer_set
Definition: 2d.h:817
int i
Definition: multi_pxo.cpp:466
#define OGL_EXT_FRAMEBUFFER_OBJECT
float ls_weight
#define MIN(a, b)
Definition: pstypes.h:296
void opengl_post_process_shutdown()
int Neb2_render_mode
Definition: neb.cpp:57
void setUniformf(const SCP_string &name, const float value)
void opengl_post_shader_header(SCP_stringstream &sflags, shader_type shader_t, int flags)
#define vglFramebufferTextureEXT
void setUniformi(const SCP_string &name, const int value)
#define vglBindFramebufferEXT
std::basic_stringstream< char, std::char_traits< char >, std::allocator< char > > SCP_stringstream
Definition: vmallocator.h:23
GLsizei const GLfloat * value
Definition: Glext.h:5646
GLint opengl_shader_get_uniform(const char *uniform_text)
int required_string_one_of(int arg_count,...)
Checks for one of any of the given required strings.
Definition: parselo.cpp:708
#define vglUniform1iARB
GLuint index
Definition: Glext.h:5608
#define GL_TEXTURE_2D_ARRAY_EXT
Definition: Glext.h:4389
void Color(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha=255)
GLuint Scene_luminance_texture
GLboolean ScissorTest(GLint state=-1)
WINGDIAPI void APIENTRY glClear(GLbitfield mask)
GLuint Shadow_map_texture
Definition: gropengltnl.cpp:84
#define GL_DEPTH_COMPONENT32
Definition: Glext.h:292
float Sun_spot
Definition: fred.cpp:708
Definition: pstypes.h:88
#define mprintf(args)
Definition: pstypes.h:238
WINGDIAPI void APIENTRY glDeleteTextures(GLsizei n, const GLuint *textures)
float ls_cpintensity
GLint GLint GLsizei GLsizei GLsizei depth
Definition: Glext.h:5180
GLuint GLuint * names
Definition: Glext.h:11016
int Fxaa_preset_last_frame
bool fxaa_unavailable
void opengl_draw_textured_quad(GLfloat x1, GLfloat y1, GLfloat u1, GLfloat v1, GLfloat x2, GLfloat y2, GLfloat u2, GLfloat v2)
Definition: gropengldraw.h:93
GLboolean DepthTest(GLint state=-1)
matrix Eye_matrix
Definition: 3dsetup.cpp:26
#define GR_ZBUFF_FULL
Definition: 2d.h:675
GLuint opengl_get_rtt_framebuffer()
Gets the current RTT framebuffer.
int light_get_global_dir(vec3d *pos, int n)
Definition: lighting.cpp:621
GLclampf f
Definition: Glext.h:7097
const char * defaults_get_file(const char *filename)
Definition: def_files.cpp:103
#define GR_ZBUFF_NONE
Definition: 2d.h:672
#define TRUE
Definition: pstypes.h:399
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
SCP_vector< opengl_shader_t > GL_shader
float ls_intensity
#define GL_TEXTURE_2D_ARRAY
Definition: Glext.h:537
opengl_texture_state Texture
GLboolean CullFace(GLint state=-1)
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
bool Post_in_frame
GLsizeiptr size
Definition: Glext.h:5496
GLuint Shadow_map_depth_texture
Definition: gropengltnl.cpp:85
GLuint Scene_depth_texture
void opengl_post_pass_fxaa()
#define GL_TEXTURE_WRAP_S
Definition: Gl.h:944
void get_post_process_effect_names(SCP_vector< SCP_string > &names)
void stuff_float(float *f)
Definition: parselo.cpp:2328
void opengl_delete_shader(int sdr_handle)
GLint GLsizei width
Definition: Gl.h:1505
#define GL_BGRA
Definition: Glext.h:78
void opengl_shader_init_uniform(const char *uniform_text)
int GL_version
Definition: gropengl.cpp:57
#define vglFramebufferTexture2DEXT
#define GL_DEPTH_ATTACHMENT_EXT
Definition: Glext.h:4205
#define GL_FALSE
Definition: Gl.h:139
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
GLboolean DepthMask(GLint state=-1)
int Game_subspace_effect
Definition: fredstubs.cpp:163
#define GL_LINEAR
Definition: Gl.h:931
struct matrix::@228::@230 vec
#define vglTexImage3D
#define GL_RGBA8
Definition: Gl.h:1007
bool ls_force_off
float clip_aspect
Definition: 2d.h:372
int Scene_texture_initialized
int cf_exists_full(const char *filename, int dir_type)
Definition: cfile.cpp:527
bool GL_rendering_to_texture
#define GL_FRAMEBUFFER_EXT
Definition: Glext.h:4207
void stuff_string(char *outstr, int type, int len, char *terminators)
Definition: parselo.cpp:1189
WINGDIAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures)
int shader_effect
Definition: ship.h:2005
#define CF_TYPE_TABLES
Definition: cfile.h:50
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
void SetAlphaBlendMode(gr_alpha_blend ab)
int required_string(const char *pstr)
Definition: parselo.cpp:468
WINGDIAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
int optional_string(const char *pstr)
Definition: parselo.cpp:539
void recompile_fxaa_shader()
void gr_opengl_post_process_end()
#define GL_RGBA32F_ARB
Definition: Glext.h:1524
#define GL_TRUE
Definition: Gl.h:138
bool invert_timer
Definition: ship.h:2004
#define GL_TEXTURE_WRAP_R
Definition: Glext.h:68
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
Definition: parselo.cpp:1995
int opengl_check_framebuffer()
int idx
Definition: multiui.cpp:761
GLuint Scene_color_texture
#define GL_TEXTURE_MAG_FILTER
Definition: Gl.h:942
float ls_density
int Cmdline_bloom_intensity
Definition: cmdline.cpp:336
opengl_uniform_state Uniform
#define Is_Extension_Enabled(x)
void SetTarget(GLenum tex_target)
WINGDIAPI void APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
int Cmdline_shadow_quality
Definition: cmdline.cpp:344
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
void Enable(GLuint tex_id=0)
int GLSL_version
Definition: gropengl.cpp:58
WINGDIAPI void APIENTRY glDrawBuffer(GLenum mode)
void read_file_text_from_array(const char *array, char *processed_text, char *raw_text)
Definition: parselo.cpp:2022
#define GL_CLAMP_TO_EDGE
Definition: Glext.h:81
void stuff_boolean(int *i, bool a_to_eol)
Definition: parselo.cpp:2519
WINGDIAPI void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
int max_w
Definition: 2d.h:360
char name[NAME_LENGTH]
Definition: ship.h:2002
GLboolean Blend(GLint state=-1)
void gr_opengl_post_process_save_zbuffer()
#define GL_UNSIGNED_INT_8_8_8_8_REV
Definition: Glext.h:75
GLbitfield flags
Definition: Glext.h:6722
SCP_vector< post_effect_t > Post_effects
unsigned char GLboolean
Definition: Gl.h:44
shader_type
Definition: 2d.h:30
void reset_parse(char *text)
Definition: parselo.cpp:3305
void gr_opengl_post_process_begin()
GLuint const GLchar * name
Definition: Glext.h:5608
int light_get_global_count()
Definition: lighting.cpp:608
GLfloat Scene_texture_u_scale
#define GL_TEXTURE_2D
Definition: Gl.h:570
void stuff_int(int *i)
Definition: parselo.cpp:2372
bool opengl_post_init_shaders()
SCP_vector< ship_effect > Ship_effects
Definition: ship.cpp:412
#define GL_TEXTURE_WRAP_T
Definition: Gl.h:945
int gr_opengl_maybe_create_shader(shader_type shader_t, unsigned int flags)
opengl_state GL_state
#define SDR_FLAG_BLUR_HORIZONTAL
Definition: 2d.h:69
GLint GLsizei GLsizei height
Definition: Gl.h:1505
#define NAME_LENGTH
Definition: globals.h:15
#define vglGenFramebuffersEXT
#define vglDeleteFramebuffersEXT
#define GL_TEXTURE_MIN_FILTER
Definition: Gl.h:943
screen gr_screen
Definition: 2d.cpp:46
GLuint Scene_normal_texture
#define OGL_ARB_TEXTURE_NON_POWER_OF_TWO
#define F_NAME
Definition: parselo.h:34
int max_h
Definition: 2d.h:360
struct post_effect_t post_effect_t
GLint GL_max_renderbuffer_size
#define PI
Definition: pstypes.h:303
void SetShaderMode(GLboolean mode)
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
int ls_samplenum
int Cmdline_fxaa_preset
Definition: cmdline.cpp:338
size_t fxaa_shader_id
int Cmdline_no_fbo
Definition: cmdline.cpp:442
WINGDIAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
#define GL_DEPTH_COMPONENT
Definition: Gl.h:779
GLuint Scene_specular_texture
#define SDR_FLAG_BLUR_VERTICAL
Definition: 2d.h:70
int temp
Definition: lua.cpp:4996
void gr_opengl_post_process_set_effect(const char *name, int value)
bool is_minimum_GLSL_version()
Definition: gropengl.cpp:2064
int Cmdline_postprocess
Definition: cmdline.cpp:335
bool PostProcessing_override
Definition: systemvars.cpp:78
#define NEB2_RENDER_NONE
Definition: neb.h:31
void opengl_post_process_init()
bool stars_sun_has_glare(int index)
Definition: starfield.cpp:2448
false
Definition: lua.cpp:6789
void opengl_shader_set_current(opengl_shader_t *shader_obj)
bool zbuffer_saved
bool Cmdline_fxaa
Definition: cmdline.cpp:337
float ls_falloff
#define GL_COLOR_BUFFER_BIT
Definition: Gl.h:96
int timer_get_milliseconds()
Definition: timer.cpp:150
bool disables_rendering
Definition: ship.h:2003
#define GL_FLOAT
Definition: Gl.h:197
#define stricmp(s1, s2)
Definition: config.h:271
GLuint Scene_position_texture
void setUniform2f(const SCP_string &name, const float x, const float y)
void SetActiveUnit(GLuint id=0)
#define GL_COLOR_ATTACHMENT0_EXT
Definition: Glext.h:4189
int opengl_check_for_errors(char *err_at)
Definition: gropengl.cpp:1252
GLint y
Definition: Gl.h:1505
#define GL_DEPTH_BUFFER_BIT
Definition: Gl.h:90
void opengl_post_init_uniforms(int flags)
#define gr_zbuffer_clear
Definition: 2d.h:818
#define strcpy_s(...)
Definition: safe_strings.h:67
#define GL_RGBA
Definition: Gl.h:785
GLboolean Lighting(GLint state=-1)
void gr_opengl_post_process_set_defaults()