FS2_Open
Open source remastering of the Freespace 2 engine
gropenglshader.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 #include "cmdline/cmdline.h"
12 #include "globalincs/def_files.h"
13 #include "graphics/2d.h"
14 #include "graphics/grinternal.h"
15 #include "graphics/gropengldraw.h"
17 #include "graphics/gropengllight.h"
20 #include "graphics/gropenglstate.h"
22 #include "graphics/gropengltnl.h"
23 #include "lighting/lighting.h"
24 #include "math/vecmat.h"
25 #include "mod_table/mod_table.h"
26 #include "render/3d.h"
27 
29 
30 static char *GLshader_info_log = NULL;
31 static const int GLshader_info_log_size = 8192;
33 
34 static int GL_anim_effect_num = 0;
35 static float GL_anim_timer = 0.0f;
36 
38 
43 static opengl_shader_type_t GL_shader_types[] = {
44  { SDR_TYPE_MODEL, "main-v.sdr", "main-f.sdr", "main-g.sdr", {GL_TRIANGLES, GL_TRIANGLE_STRIP, 3},
45  0, {}, 0, {}, "Model Rendering" },
46 
47  { SDR_TYPE_EFFECT_PARTICLE, "effect-v.sdr", "effect-particle-f.sdr", "effect-screen-g.sdr", {GL_POINTS, GL_TRIANGLE_STRIP, 4},
48  7, { "baseMap", "depthMap", "window_width", "window_height", "nearZ", "farZ", "linear_depth" }, 1, {"radius"}, "Particle Effects" },
49 
50  { SDR_TYPE_EFFECT_DISTORTION, "effect-distort-v.sdr", "effect-distort-f.sdr", 0, { 0, 0, 0 },
51  6, { "baseMap", "window_width", "window_height", "distMap", "frameBuffer", "use_offset" }, 1, { "radius" }, "Distortion Effects" },
52 
53  { SDR_TYPE_POST_PROCESS_MAIN, "post-v.sdr", "post-f.sdr", 0, {0, 0, 0},
54  5, { "tex", "depth_tex", "timer", "bloomed", "bloom_intensity" }, 0, { NULL }, "Post Processing" },
55 
56  { SDR_TYPE_POST_PROCESS_BLUR, "post-v.sdr", "blur-f.sdr", 0, {0, 0, 0},
57  2, { "tex", "bsize", "debug" }, 0, { NULL }, "Gaussian Blur" },
58 
59  { SDR_TYPE_POST_PROCESS_BRIGHTPASS, "post-v.sdr", "brightpass-f.sdr", 0, { 0, 0, 0 },
60  1, { "tex" }, 0, { NULL }, "Bloom Brightpass" },
61 
62  { SDR_TYPE_POST_PROCESS_FXAA, "fxaa-v.sdr", "fxaa-f.sdr", 0, {0, 0, 0},
63  3, { "tex0", "rt_w", "rt_h" }, 0, { NULL }, "FXAA" },
64 
65  { SDR_TYPE_POST_PROCESS_FXAA_PREPASS, "post-v.sdr", "fxaapre-f.sdr", 0, {0, 0, 0},
66  1, { "tex" }, 0, { NULL }, "FXAA Prepass" },
67 
68  { SDR_TYPE_POST_PROCESS_LIGHTSHAFTS, "post-v.sdr", "ls-f.sdr", 0, {0, 0, 0},
69  8, { "scene", "cockpit", "sun_pos", "weight", "intensity", "falloff", "density", "cp_intensity" }, 0, { NULL }, "Lightshafts" },
70 
71  { SDR_TYPE_DEFERRED_LIGHTING, "deferred-v.sdr", "deferred-f.sdr", 0, { 0, 0, 0 },
72  16, { "scale", "ColorBuffer", "NormalBuffer", "PositionBuffer", "SpecBuffer", "invScreenWidth", "invScreenHeight", "lightType", "lightRadius", "diffuseLightColor",
73  "specLightColor", "dualCone", "coneDir", "coneAngle", "coneInnerAngle", "specFactor" }, 0, { NULL }, "Deferred Lighting" },
74 
75  { SDR_TYPE_DEFERRED_CLEAR, "deferred-clear-v.sdr", "deferred-clear-f.sdr", 0, {0, 0, 0},
76  0, { NULL }, 0, { NULL }, "Clear Deferred Lighting Buffer" },
77 
78  { SDR_TYPE_VIDEO_PROCESS, "video-v.sdr", "video-f.sdr", 0, {0, 0, 0},
79  3, { "ytex", "utex", "vtex" }, 0, { NULL }, "Video Playback" }
80 };
81 
86 static opengl_shader_variant_t GL_shader_variants[] = {
87  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_LIGHT, "FLAG_LIGHT",
88  2, { "n_lights", "light_factor" }, 0, { NULL },
89  "Lighting" },
90 
91  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_FOG, "FLAG_FOG",
92  0, { NULL }, 0, { NULL },
93  "Fog Effect" },
94 
95  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_DIFFUSE_MAP, "FLAG_DIFFUSE_MAP",
96  4, { "sBasemap", "desaturate", "desaturate_clr", "blend_alpha" }, 0, { NULL },
97  "Diffuse Mapping" },
98 
99  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_GLOW_MAP, "FLAG_GLOW_MAP",
100  1, { "sGlowmap" }, 0, { NULL },
101  "Glow Mapping" },
102 
103  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_SPEC_MAP, "FLAG_SPEC_MAP",
104  1, { "sSpecmap" }, 0, { NULL },
105  "Specular Mapping" },
106 
107  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_NORMAL_MAP, "FLAG_NORMAL_MAP",
108  1, { "sNormalmap" }, 0, { NULL },
109  "Normal Mapping" },
110 
111  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_HEIGHT_MAP, "FLAG_HEIGHT_MAP",
112  1, { "sHeightmap" }, 0, { NULL },
113  "Parallax Mapping" },
114 
115  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_ENV_MAP, "FLAG_ENV_MAP",
116  3, { "sEnvmap", "alpha_spec", "envMatrix" }, 0, { NULL },
117  "Environment Mapping" },
118 
119  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_ANIMATED, "FLAG_ANIMATED",
120  5, { "sFramebuffer", "effect_num", "anim_timer", "vpwidth", "vpheight" }, 0, { NULL },
121  "Animated Effects" },
122 
123  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_MISC_MAP, "FLAG_MISC_MAP",
124  1, { "sMiscmap" }, 0, { NULL },
125  "Utility mapping" },
126 
127  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_TEAMCOLOR, "FLAG_TEAMCOLOR",
128  3, { "stripe_color", "base_color", "team_glow_enabled" }, 0, { NULL },
129  "Team Colors" },
130 
131  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_DEFERRED, "FLAG_DEFERRED",
132  0, { NULL }, 0, { NULL },
133  "Deferred lighting" },
134 
135  { SDR_TYPE_MODEL, true, SDR_FLAG_MODEL_SHADOW_MAP, "FLAG_SHADOW_MAP",
136  1, { "shadow_proj_matrix" }, 0, { NULL },
137  "Shadow Mapping" },
138 
139  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_SHADOWS, "FLAG_SHADOWS",
140  8, { "shadow_map", "shadow_mv_matrix", "shadow_proj_matrix", "model_matrix", "veryneardist", "neardist", "middist", "fardist" }, 0, { NULL },
141  "Shadows" },
142 
143  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_THRUSTER, "FLAG_THRUSTER",
144  1, { "thruster_scale" }, 0, { NULL },
145  "Thruster scaling" },
146 
147  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_TRANSFORM, "FLAG_TRANSFORM",
148  2, { "transform_tex", "buffer_matrix_offset" }, 1, { "model_id" },
149  "Submodel Transforms" },
150 
151  { SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_CLIP, "FLAG_CLIP",
152  4, { "use_clip_plane", "world_matrix", "clip_normal", "clip_position" }, 0, { NULL },
153  "Clip Plane" },
154 
155  { SDR_TYPE_EFFECT_PARTICLE, true, SDR_FLAG_PARTICLE_POINT_GEN, "FLAG_EFFECT_GEOMETRY",
156  0, { NULL }, 1, { "uvec" },
157  "Geometry shader point-based particles" },
158 
160  0, { NULL }, 0, { NULL },
161  "Horizontal blur pass" },
162 
164  0, { NULL }, 0, { NULL },
165  "Vertical blur pass" }
166 };
167 
168 static const int GL_num_shader_variants = sizeof(GL_shader_variants) / sizeof(opengl_shader_variant_t);
169 
171 
172 // Forward declarations
174 void opengl_shader_check_info_log(GLhandleARB shader_object);
175 
181 {
182  if (shader_obj != NULL) {
183  if(!Current_shader || (Current_shader->program_id != shader_obj->program_id)) {
184  Current_shader = shader_obj;
185  vglUseProgramObjectARB(Current_shader->program_id);
187 #ifndef NDEBUG
188  if ( opengl_check_for_errors("shader_set_current()") ) {
189  vglValidateProgramARB(Current_shader->program_id);
190 
191  GLint obj_status = 0;
193 
194  if ( !obj_status ) {
195  opengl_shader_check_info_log(Current_shader->program_id);
196 
197  mprintf(("VALIDATE INFO-LOG:\n"));
198 
199  if (strlen(GLshader_info_log) > 5) {
200  mprintf(("%s\n", GLshader_info_log));
201  } else {
202  mprintf(("<EMPTY>\n"));
203  }
204  }
205  }
206 #endif
207  }
208  } else {
209  Current_shader = NULL;
211  }
212 }
213 
215 {
216  Assert(handle >= 0);
217  Assert(handle < (int)GL_shader.size());
218 
219  opengl_shader_set_current(&GL_shader[handle]);
220 }
221 
230 {
232  return -1;
233 
234  size_t idx;
235  size_t max = GL_shader.size();
236 
237  for (idx = 0; idx < max; idx++) {
238  if (GL_shader[idx].shader == shader_t && GL_shader[idx].flags == flags) {
239  return idx;
240  }
241  }
242 
243  // If we are here, it means we need to compile a new shader
244  return opengl_compile_shader(shader_t, flags);
245 }
246 
247 void opengl_delete_shader(int sdr_handle)
248 {
249  Assert(sdr_handle >= 0);
250  Assert(sdr_handle < (int)GL_shader.size());
251 
252  if (GL_shader[sdr_handle].program_id) {
253  vglDeleteObjectARB(GL_shader[sdr_handle].program_id);
254  GL_shader[sdr_handle].program_id = 0;
255  }
256 
257  GL_shader[sdr_handle].flags = 0;
258  GL_shader[sdr_handle].flags2 = 0;
259  GL_shader[sdr_handle].shader = NUM_SHADER_TYPES;
260 
261  GL_shader[sdr_handle].uniforms.clear();
262  GL_shader[sdr_handle].attributes.clear();
263  GL_shader[sdr_handle].uniform_blocks.clear();
264 }
265 
270 {
271  size_t i;
272 
273  if ( !is_minimum_GLSL_version() ) {
274  return;
275  }
276 
277  for (i = 0; i < GL_shader.size(); i++) {
278  if (GL_shader[i].program_id) {
279  vglDeleteObjectARB(GL_shader[i].program_id);
280  GL_shader[i].program_id = 0;
281  }
282 
283  GL_shader[i].uniforms.clear();
284  GL_shader[i].attributes.clear();
285  GL_shader[i].uniform_blocks.clear();
286  }
287 
288  GL_shader.clear();
289 
290  if (GLshader_info_log != NULL) {
291  vm_free(GLshader_info_log);
292  GLshader_info_log = NULL;
293  }
294 }
295 
296 static SCP_string get_shader_header(shader_type type_id, int flags) {
297  SCP_stringstream sflags;
298 
299 #ifdef __APPLE__
300  sflags << "#version 120\n";
301  sflags << "#define APPLE\n";
302 #endif
303 
305  // ignore looking for variants. main post process, lightshafts, and FXAA shaders need special headers to be hacked in
306  opengl_post_shader_header(sflags, type_id, flags);
307  }
308  else {
309  for (int i = 0; i < GL_num_shader_variants; ++i) {
310  opengl_shader_variant_t &variant = GL_shader_variants[i];
311 
312  if (type_id == variant.type_id && flags & variant.flag) {
313  sflags << "#define " << variant.flag_text << "\n";
314  }
315  }
316  }
317 
318  return sflags.str();
319 }
320 
331 static SCP_string opengl_load_shader(const char *filename)
332 {
333  SCP_string content;
335  CFILE *cf_shader = cfopen(filename, "rt", CFILE_NORMAL, CF_TYPE_EFFECTS);
336 
337  if (cf_shader != NULL) {
338  int len = cfilelength(cf_shader);
339  content.resize(len);
340 
341  cfread(&content[0], len + 1, 1, cf_shader);
342  cfclose(cf_shader);
343 
344  return content;
345  }
346  }
347 
348  //If we're still here, proceed with internals
349  mprintf((" Loading built-in default shader for: %s\n", filename));
350  auto def_shader = defaults_get_file(filename);
351  content.assign(def_shader);
352 
353  return content;
354 }
355 
356 static SCP_vector<SCP_string> opengl_get_shader_content(shader_type type_id, const char* filename, int flags) {
358  parts.push_back(get_shader_header(type_id, flags));
359 
360  parts.push_back(opengl_load_shader(filename));
361 
362  return parts;
363 }
364 
373 {
374  int sdr_index = -1;
375  int empty_idx;
376  opengl_shader_t new_shader;
377 
378  Assert(sdr < NUM_SHADER_TYPES);
379 
380  opengl_shader_type_t *sdr_info = &GL_shader_types[sdr];
381 
382  mprintf(("Compiling new shader:\n"));
383  mprintf((" %s\n", sdr_info->description));
384 
385  // figure out if the variant requested needs a geometry shader
386  bool use_geo_sdr = false;
387 
388  // do we even have a geometry shader?
389  if ( sdr_info->geo != NULL ) {
390  for (int i = 0; i < GL_num_shader_variants; ++i) {
391  opengl_shader_variant_t *variant = &GL_shader_variants[i];
392 
393  if (variant->type_id == sdr && flags & variant->flag && variant->use_geometry_sdr) {
394  use_geo_sdr = true;
395  break;
396  }
397  }
398  }
399 
400  auto vertex_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->vert, flags);
401  auto fragment_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->frag, flags);
402  SCP_vector<SCP_string> geom_content;
403 
404  if ( use_geo_sdr ) {
406  return -1;
407  }
408 
409  // read geometry shader
410  geom_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->geo, flags);
411 
412  Current_geo_sdr_params = &sdr_info->geo_sdr_info;
413  }
414 
415  new_shader.program_id = opengl_shader_create(vertex_content, fragment_content, geom_content);
416 
417  if (!new_shader.program_id) {
418  return -1;
419  }
420 
421  new_shader.shader = sdr_info->type_id;
422  new_shader.flags = flags;
423 
424  opengl_shader_set_current(&new_shader);
425 
426  // initialize uniforms and attributes
427  for ( int i = 0; i < sdr_info->num_uniforms; ++i ) {
428  opengl_shader_init_uniform( sdr_info->uniforms[i] );
429  }
430 
431  for (int i = 0; i < sdr_info->num_attributes; ++i) {
433  }
434 
435  // if this shader is POST_PROCESS_MAIN, hack in the user-defined flags
436  if ( sdr_info->type_id == SDR_TYPE_POST_PROCESS_MAIN ) {
438  }
439 
440  mprintf(("Shader Variant Features:\n"));
441 
442  // initialize all uniforms and attributes that are specific to this variant
443  for ( int i = 0; i < GL_num_shader_variants; ++i ) {
444  opengl_shader_variant_t &variant = GL_shader_variants[i];
445 
446  if ( sdr_info->type_id == variant.type_id && variant.flag & flags ) {
447  for (int j = 0; j < variant.num_uniforms; ++j) {
449  }
450 
451  for (int j = 0; j < variant.num_attributes; ++j) {
453  }
454 
455  mprintf((" %s\n", variant.description));
456  }
457  }
458 
460 
461  // add it to our list of embedded shaders
462  // see if we have empty shader slots
463  empty_idx = -1;
464  for ( int i = 0; i < (int)GL_shader.size(); ++i ) {
465  if ( GL_shader[i].shader == NUM_SHADER_TYPES ) {
466  empty_idx = i;
467  break;
468  }
469  }
470 
471  // then insert it at an empty slot or at the end
472  if ( empty_idx >= 0 ) {
473  GL_shader[empty_idx] = new_shader;
474  sdr_index = empty_idx;
475  } else {
476  sdr_index = GL_shader.size();
477  GL_shader.push_back(new_shader);
478  }
479 
480  return sdr_index;
481 }
482 
488 {
489  if ( !is_minimum_GLSL_version() ) {
490  return;
491  }
492 
497 
503  GLuint pixels[4] = {0,0,0,0};
505 
506  GL_shader.clear();
507 
508  // Reserve 32 shader slots. This should cover most use cases in real life.
509  GL_shader.reserve(32);
510 
511  // compile effect shaders
515 
516  // compile deferred lighting shaders
518  mprintf(("\n"));
519 }
520 
527 {
528  if (GLshader_info_log == NULL) {
529  GLshader_info_log = (char *) vm_malloc(GLshader_info_log_size);
530  }
531 
532  memset(GLshader_info_log, 0, GLshader_info_log_size);
533 
534  vglGetInfoLogARB(shader_object, GLshader_info_log_size-1, 0, GLshader_info_log);
535 }
536 
547 {
548  GLhandleARB shader_object = 0;
549  GLint status = 0;
550 
552  sources.reserve(shader_source.size());
553  for (auto it = shader_source.begin(); it != shader_source.end(); ++it) {
554  sources.push_back(it->c_str());
555  }
556 
557  shader_object = vglCreateShaderObjectARB(shader_type);
558 
559  vglShaderSourceARB(shader_object, sources.size(), &sources[0], NULL);
560  vglCompileShaderARB(shader_object);
561 
562  // check if the compile was successful
564 
565  opengl_shader_check_info_log(shader_object);
566 
567  // we failed, bail out now...
568  if (status == 0) {
569  // basic error check
570  mprintf(("%s shader failed to compile:\n%s\n", (shader_type == GL_VERTEX_SHADER_ARB) ? "Vertex" : ((shader_type == GL_GEOMETRY_SHADER_EXT) ? "Geometry" : "Fragment"), GLshader_info_log));
571 
572  // this really shouldn't exist, but just in case
573  if (shader_object) {
574  vglDeleteObjectARB(shader_object);
575  }
576 
577  return 0;
578  }
579 
580  // we succeeded, maybe output warnings too
581  if (strlen(GLshader_info_log) > 5) {
582  nprintf(("SHADER-DEBUG", "%s shader compiled with warnings:\n%s\n", (shader_type == GL_VERTEX_SHADER_ARB) ? "Vertex" : ((shader_type == GL_GEOMETRY_SHADER_EXT) ? "Geometry" : "Fragment"), GLshader_info_log));
583  }
584 
585  return shader_object;
586 }
587 
599 GLhandleARB opengl_shader_link_object(GLhandleARB vertex_object, GLhandleARB fragment_object, GLhandleARB geometry_object)
600 {
601  GLhandleARB shader_object = 0;
602  GLint status = 0;
603 
604  shader_object = vglCreateProgramObjectARB();
605 
606  if (vertex_object) {
607  vglAttachObjectARB(shader_object, vertex_object);
608  }
609 
610  if (fragment_object) {
611  vglAttachObjectARB(shader_object, fragment_object);
612  }
613 
614  if (geometry_object) {
615  vglAttachObjectARB(shader_object, geometry_object);
616 
617  if ( Current_geo_sdr_params != NULL) {
618 #ifdef __APPLE__
619  vglProgramParameteriEXT((long)shader_object, GL_GEOMETRY_INPUT_TYPE_EXT, Current_geo_sdr_params->input_type);
620  vglProgramParameteriEXT((long)shader_object, GL_GEOMETRY_OUTPUT_TYPE_EXT, Current_geo_sdr_params->output_type);
621  vglProgramParameteriEXT((long)shader_object, GL_GEOMETRY_VERTICES_OUT_EXT, Current_geo_sdr_params->vertices_out);
622 #else
623  vglProgramParameteriEXT((GLuint)shader_object, GL_GEOMETRY_INPUT_TYPE_EXT, Current_geo_sdr_params->input_type);
624  vglProgramParameteriEXT((GLuint)shader_object, GL_GEOMETRY_OUTPUT_TYPE_EXT, Current_geo_sdr_params->output_type);
625  vglProgramParameteriEXT((GLuint)shader_object, GL_GEOMETRY_VERTICES_OUT_EXT, Current_geo_sdr_params->vertices_out);
626 #endif
627  }
628  }
629  vglLinkProgramARB(shader_object);
630 
631  // check if the link was successful
632  vglGetObjectParameterivARB(shader_object, GL_OBJECT_LINK_STATUS_ARB, &status);
633 
634  opengl_shader_check_info_log(shader_object);
635 
636  // we failed, bail out now...
637  if (status == 0) {
638  mprintf(("Shader failed to link:\n%s\n", GLshader_info_log));
639 
640  if (shader_object) {
641  vglDeleteObjectARB(shader_object);
642  }
643 
644  return 0;
645  }
646 
647  // we succeeded, maybe output warnings too
648  if (strlen(GLshader_info_log) > 5) {
649  nprintf(("SHADER-DEBUG", "Shader linked with warnings:\n%s\n", GLshader_info_log));
650  }
651 
652  return shader_object;
653 }
654 
664 {
665  GLhandleARB vs_o = 0;
666  GLhandleARB fs_o = 0;
667  GLhandleARB gs_o = 0;
668  GLhandleARB program = 0;
669 
670  if (!vs.empty()) {
672 
673  if ( !vs_o ) {
674  mprintf(("ERROR! Unable to create vertex shader!\n"));
675  goto Done;
676  }
677  }
678 
679  if (!fs.empty()) {
681 
682  if ( !fs_o ) {
683  mprintf(("ERROR! Unable to create fragment shader!\n"));
684  goto Done;
685  }
686  }
687 
688  if (!gs.empty()) {
690 
691  if ( !gs_o ) {
692  mprintf(("ERROR! Unable to create fragment shader!\n"));
693  goto Done;
694  }
695  }
696 
697  program = opengl_shader_link_object(vs_o, fs_o, gs_o);
698 
699  if ( !program ) {
700  mprintf(("ERROR! Unable to create shader program!\n"));
701  }
702 
703 Done:
704  if (vs_o) {
705  vglDeleteObjectARB(vs_o);
706  }
707 
708  if (fs_o) {
709  vglDeleteObjectARB(fs_o);
710  }
711 
712  if (gs_o) {
713  vglDeleteObjectARB(gs_o);
714  }
715 
716  return program;
717 }
718 
724 void opengl_shader_init_attribute(const char *attribute_text)
725 {
726  opengl_shader_uniform_t new_attribute;
727 
728  if ( ( Current_shader == NULL ) || ( attribute_text == NULL ) ) {
729  Int3();
730  return;
731  }
732 
733  new_attribute.text_id = attribute_text;
734  new_attribute.location = vglGetAttribLocationARB(Current_shader->program_id, attribute_text);
735 
736  if ( new_attribute.location < 0 ) {
737  nprintf(("SHADER-DEBUG", "WARNING: Unable to get shader attribute location for \"%s\"!\n", attribute_text));
738  return;
739  }
740 
741  Current_shader->attributes.push_back( new_attribute );
742 }
743 
750 GLint opengl_shader_get_attribute(const char *attribute_text)
751 {
752  if ( (Current_shader == NULL) || (attribute_text == NULL) ) {
753  Int3();
754  return -1;
755  }
756 
758 
759  for (attribute = Current_shader->attributes.begin(); attribute != Current_shader->attributes.end(); ++attribute) {
760  if ( !attribute->text_id.compare(attribute_text) ) {
761  return attribute->location;
762  }
763  }
764 
765  return -1;
766 }
767 
773 void opengl_shader_init_uniform(const char *uniform_text)
774 {
775  opengl_shader_uniform_t new_uniform;
776 
777  if ( (Current_shader == NULL) || (uniform_text == NULL) ) {
778  Int3();
779  return;
780  }
781 
782  new_uniform.text_id = uniform_text;
783  new_uniform.location = vglGetUniformLocationARB(Current_shader->program_id, uniform_text);
784 
785  if (new_uniform.location < 0) {
786  nprintf(("SHADER-DEBUG", "WARNING: Unable to get shader uniform location for \"%s\"!\n", uniform_text));
787  return;
788  }
789 
790  Current_shader->uniforms.push_back( new_uniform );
791 }
792 
799 GLint opengl_shader_get_uniform(const char *uniform_text)
800 {
801  if ( (Current_shader == NULL) || (uniform_text == NULL) ) {
802  Int3();
803  return -1;
804  }
805 
807  SCP_vector<opengl_shader_uniform_t>::iterator uniforms_end = Current_shader->uniforms.end();
808 
809  for (uniform = Current_shader->uniforms.begin(); uniform != uniforms_end; ++uniform) {
810  if ( !uniform->text_id.compare(uniform_text) ) {
811  return uniform->location;
812  }
813  }
814 
815  return -1;
816 }
817 
823 void opengl_shader_init_uniform_block(const char *uniform_text)
824 {
825  opengl_shader_uniform_t new_uniform_block;
826 
827  if ( (Current_shader == NULL) || (uniform_text == NULL) ) {
828  Int3();
829  return;
830  }
831 
832  new_uniform_block.text_id = uniform_text;
833 #ifdef __APPLE__
834  new_uniform_block.location = vglGetUniformBlockIndexARB((long)Current_shader->program_id, uniform_text);
835 #else
836  new_uniform_block.location = vglGetUniformBlockIndexARB(Current_shader->program_id, uniform_text);
837 #endif
838  if (new_uniform_block.location < 0) {
839  nprintf(("SHADER-DEBUG", "WARNING: Unable to get shader uniform block location for \"%s\"!\n", uniform_text));
840  return;
841  }
842 
843  Current_shader->uniform_blocks.push_back( new_uniform_block );
844 }
845 
852 GLint opengl_shader_get_uniform_block(const char *uniform_text)
853 {
854  if ( (Current_shader == NULL) || (uniform_text == NULL) ) {
855  Int3();
856  return -1;
857  }
858 
860 
861  for (uniform_block = Current_shader->uniform_blocks.begin(); uniform_block != Current_shader->uniform_blocks.end(); ++uniform_block) {
862  if ( !uniform_block->text_id.compare(uniform_text) ) {
863  return uniform_block->location;
864  }
865  }
866 
867  return -1;
868 }
869 
876 void gr_opengl_shader_set_animated_effect(int effect, float timer)
877 {
878  GL_anim_effect_num = effect;
879  GL_anim_timer = timer;
880 }
881 
888 {
889  return GL_anim_effect_num;
890 }
891 
896 {
897  return GL_anim_timer;
898 }
899 
904 {
905  bool in_error = false;
906 
908 
909  if ( sdr_handle >= 0 ) {
910  opengl_shader_set_current(sdr_handle);
911 
912  GL_state.Uniform.setUniformi("ColorBuffer", 0);
913  GL_state.Uniform.setUniformi("NormalBuffer", 1);
914  GL_state.Uniform.setUniformi("PositionBuffer", 2);
915  GL_state.Uniform.setUniformi("SpecBuffer", 3);
916  GL_state.Uniform.setUniformf("invScreenWidth", 1.0f / gr_screen.max_w);
917  GL_state.Uniform.setUniformf("invScreenHeight", 1.0f / gr_screen.max_h);
919  } else {
921  mprintf(("Failed to compile deferred lighting shader!\n"));
922  in_error = true;
923  }
924 
926  mprintf(("Failed to compile deferred lighting buffer clear shader!\n"));
927  in_error = true;
928  }
929 
930  if ( in_error ) {
931  mprintf((" Shader in_error! Disabling deferred lighting!\n"));
933  }
934 }
unsigned int GLuint
Definition: Gl.h:52
#define vglShaderSourceARB
unsigned int GLhandleARB
Definition: Glext.h:5080
#define OGL_EXT_GEOMETRY_SHADER4
#define vglProgramParameteriEXT
#define CFILE_NORMAL
Definition: cfile.h:89
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
#define GL_GEOMETRY_VERTICES_OUT_EXT
Definition: Glext.h:4311
void opengl_shader_compile_deferred_light_shader()
#define vglGetUniformBlockIndexARB
void setUniformf(const SCP_string &name, const float value)
LOCAL state_stack gs[GS_STACK_SIZE]
void opengl_post_shader_header(SCP_stringstream &sflags, shader_type shader_t, int flags)
void setUniformi(const SCP_string &name, const int value)
#define vglGetInfoLogARB
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
std::basic_stringstream< char, std::char_traits< char >, std::allocator< char > > SCP_stringstream
Definition: vmallocator.h:23
GLint opengl_shader_get_uniform(const char *uniform_text)
#define SDR_FLAG_MODEL_CLIP
Definition: 2d.h:65
#define vglCompileShaderARB
char * uniforms[MAX_SHADER_UNIFORMS]
Assert(pm!=NULL)
#define mprintf(args)
Definition: pstypes.h:238
#define SDR_FLAG_MODEL_DIFFUSE_MAP
Definition: 2d.h:50
#define GL_TRIANGLES
Definition: Gl.h:109
#define vglGetUniformLocationARB
GLclampf f
Definition: Glext.h:7097
const char * defaults_get_file(const char *filename)
Definition: def_files.cpp:103
Definition: cfile.h:28
unsigned int flags
Definition: 2d.h:82
SCP_vector< opengl_shader_t > GL_shader
#define SDR_FLAG_MODEL_DEFERRED
Definition: 2d.h:60
opengl_texture_state Texture
#define GL_FRAGMENT_SHADER_ARB
Definition: Glext.h:1456
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
GLint opengl_shader_get_uniform_block(const char *uniform_text)
#define Int3()
Definition: pstypes.h:292
#define SDR_FLAG_MODEL_LIGHT
Definition: 2d.h:48
#define GL_TEXTURE_WRAP_S
Definition: Gl.h:944
#define vglGetAttribLocationARB
#define SDR_FLAG_MODEL_FOG
Definition: 2d.h:49
GLint opengl_shader_get_attribute(const char *attribute_text)
opengl_shader_t * Current_shader
#define SDR_FLAG_PARTICLE_POINT_GEN
Definition: 2d.h:67
void opengl_delete_shader(int sdr_handle)
#define GL_BGRA
Definition: Glext.h:78
void opengl_shader_init_uniform(const char *uniform_text)
#define SDR_FLAG_MODEL_MISC_MAP
Definition: 2d.h:57
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define SDR_FLAG_MODEL_SPEC_MAP
Definition: 2d.h:52
#define GL_LINEAR
Definition: Gl.h:931
unsigned int uint
Definition: pstypes.h:64
#define GL_OBJECT_VALIDATE_STATUS_ARB
Definition: Glext.h:1437
#define cfopen(...)
Definition: cfile.h:134
#define GL_RGBA8
Definition: Gl.h:1007
#define nprintf(args)
Definition: pstypes.h:239
void opengl_shader_shutdown()
void opengl_shader_init_uniform_block(const char *uniform_text)
#define SDR_FLAG_MODEL_SHADOW_MAP
Definition: 2d.h:61
char * filename
WINGDIAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures)
WINGDIAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
GLsizei GLenum * sources
Definition: Glext.h:7310
#define vglValidateProgramARB
#define SDR_FLAG_MODEL_NORMAL_MAP
Definition: 2d.h:53
#define GL_TEXTURE_WRAP_R
Definition: Glext.h:68
int idx
Definition: multiui.cpp:761
#define GL_TEXTURE_MAG_FILTER
Definition: Gl.h:942
opengl_uniform_state Uniform
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: Glext.h:5180
#define Is_Extension_Enabled(x)
char * uniforms[MAX_SHADER_UNIFORMS]
void SetTarget(GLenum tex_target)
int Cmdline_no_deferred_lighting
Definition: cmdline.cpp:345
void Enable(GLuint tex_id=0)
GLhandleARB program_id
char * attributes[MAX_SDR_ATTRIBUTES]
#define GL_CLAMP_TO_EDGE
Definition: Glext.h:81
GLuint Framebuffer_fallback_texture_id
SCP_vector< opengl_shader_uniform_t > uniform_blocks
int max_w
Definition: 2d.h:360
const char * description
#define GL_GEOMETRY_OUTPUT_TYPE_EXT
Definition: Glext.h:4313
float opengl_shader_get_animated_timer()
#define SDR_FLAG_MODEL_TEAMCOLOR
Definition: 2d.h:58
int opengl_compile_shader(shader_type sdr, uint flags)
#define GL_UNSIGNED_INT_8_8_8_8_REV
Definition: Glext.h:75
GLbitfield flags
Definition: Glext.h:6722
#define vm_malloc(size)
Definition: pstypes.h:547
shader_type
Definition: 2d.h:30
#define SDR_FLAG_MODEL_GLOW_MAP
Definition: 2d.h:51
#define vglCreateShaderObjectARB
#define GL_TEXTURE_2D
Definition: Gl.h:570
#define SDR_FLAG_MODEL_ENV_MAP
Definition: 2d.h:55
#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
#define SDR_FLAG_MODEL_HEIGHT_MAP
Definition: 2d.h:54
#define GL_OBJECT_LINK_STATUS_ARB
Definition: Glext.h:1436
SCP_vector< opengl_shader_uniform_t > attributes
int opengl_shader_get_animated_effect()
#define GL_TEXTURE_MIN_FILTER
Definition: Gl.h:943
screen gr_screen
Definition: 2d.cpp:46
#define GL_VERTEX_SHADER_ARB
Definition: Glext.h:1446
GLhandleARB opengl_shader_link_object(GLhandleARB vertex_object, GLhandleARB fragment_object, GLhandleARB geometry_object)
void opengl_shader_check_info_log(GLhandleARB shader_object)
#define GL_GEOMETRY_INPUT_TYPE_EXT
Definition: Glext.h:4312
GLhandleARB opengl_shader_compile_object(const SCP_vector< SCP_string > &shader_source, GLenum shader_type)
#define SDR_FLAG_MODEL_SHADOWS
Definition: 2d.h:63
int max_h
Definition: 2d.h:360
void opengl_shader_init_attribute(const char *attribute_text)
#define GL_GEOMETRY_SHADER_EXT
Definition: Glext.h:4323
#define vglAttachObjectARB
GLuint program
Definition: Glext.h:6284
GLhandleARB opengl_shader_create(const SCP_vector< SCP_string > &vs, const SCP_vector< SCP_string > &fs, const SCP_vector< SCP_string > &gs)
float Cmdline_ogl_spec
Definition: cmdline.cpp:321
#define CF_TYPE_EFFECTS
Definition: cfile.h:65
#define GL_POINTS
Definition: Gl.h:105
unsigned int GLenum
Definition: Gl.h:43
SCP_vector< opengl_shader_uniform_t > uniforms
char * attributes[MAX_SDR_ATTRIBUTES]
GLenum GLsizei len
Definition: Glext.h:6283
void opengl_shader_init()
WINGDIAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
#define SDR_FLAG_MODEL_ANIMATED
Definition: 2d.h:56
#define SDR_FLAG_BLUR_VERTICAL
Definition: 2d.h:70
bool is_minimum_GLSL_version()
Definition: gropengl.cpp:2064
bool Enable_external_shaders
Definition: mod_table.cpp:27
shader_type shader
void opengl_shader_set_current(opengl_shader_t *shader_obj)
#define GL_OBJECT_COMPILE_STATUS_ARB
Definition: Glext.h:1435
geometry_sdr_params * Current_geo_sdr_params
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
#define SDR_FLAG_MODEL_TRANSFORM
Definition: 2d.h:59
#define vglCreateProgramObjectARB
#define vglUseProgramObjectARB
#define vglDeleteObjectARB
#define SDR_FLAG_MODEL_THRUSTER
Definition: 2d.h:64
int cfilelength(CFILE *cfile)
Definition: cfile.cpp:1393
void gr_opengl_shader_set_animated_effect(int effect, float timer)
void SetActiveUnit(GLuint id=0)
int opengl_check_for_errors(char *err_at)
Definition: gropengl.cpp:1252
void opengl_post_init_uniforms(int flags)
int GLint
Definition: Gl.h:48
geometry_sdr_params geo_sdr_info
#define GL_TRIANGLE_STRIP
Definition: Gl.h:110
#define vglLinkProgramARB
#define vglGetObjectParameterivARB