GLfloat opengl_texture_state::AnisoFilter(GLfloat aniso) { #if 0 GLfloat rval = units[active_texture_unit].aniso_filter; if ( (aniso > 0.0f) /*&& (aniso != rval)*/ ) { if ( Is_Extension_Enabled(OGL_EXT_TEXTURE_FILTER_ANISOTROPIC) ) { units[active_texture_unit].aniso_filter = aniso; CLAMP(units[active_texture_unit].aniso_filter, 1.0f, GL_max_anisotropy); glTexParameterf(units[active_texture_unit].texture_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, units[active_texture_unit].aniso_filter); } if ( Is_Extension_Enabled(OGL_EXT_TEXTURE_LOD_BIAS) ) { if (units[active_texture_unit].aniso_filter > 1.0f) { glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f); } else { glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.75f); } } } return rval; #endif return GL_anisotropy; }
int gr_opengl_bm_make_render_target(int n, int *width, int *height, ubyte *bpp, int *mm_lvl, int flags) { Assert( (n >= 0) && (n < MAX_BITMAPS) ); if ( !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) || Cmdline_no_fbo ) { return 0; } if ( (flags & BMP_FLAG_CUBEMAP) && !Is_Extension_Enabled(OGL_ARB_TEXTURE_CUBE_MAP) ) { return 0; } if ( (flags & BMP_FLAG_CUBEMAP) && (*width != *height) ) { MIN(*width, *height) = MAX(*width, *height); } // Only enforce power of two size if not supported if (!(Is_Extension_Enabled(OGL_ARB_TEXTURE_NON_POWER_OF_TWO))) { Assert( is_power_of_two(*width, *height) ); } if ( opengl_make_render_target(bm_bitmaps[n].handle, n, width, height, bpp, mm_lvl, flags) ) { return 1; } return 0; }
int distortion_add_beam(int texture, int tmap_flags, vec3d *start, vec3d *end, float width, float intensity, float offset) { if (texture < 0) { Int3(); return 1; } if ( GLSL_version < 120 || !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) ) { // don't render distortions if we can't support them. return 0; } batch_item *item = NULL; SCP_map<int, batch_item>::iterator it = distortion_map.find(texture); if ( !distortion_map.empty() && it != distortion_map.end() ) { item = &it->second; } else { item = &distortion_map[texture]; item->texture = texture; } Assertion( (item->laser == false), "Distortion particle effect %s used as laser glow or laser bitmap\n", bm_get_filename(texture) ); item->tmap_flags = tmap_flags; item->alpha = intensity; item->batch.add_allocate(1); item->batch.draw_beam(start,end,width,intensity,offset); return 0; }
void opengl_post_process_init() { Post_initialized = 0; //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. if ( !opengl_post_init_table() ) { mprintf((" Unable to read post-processing table! Disabling post-processing...\n\n")); Cmdline_postprocess = 0; return; } if ( !Cmdline_postprocess ) { return; } if ( !Scene_texture_initialized ) { return; } if ( !is_minimum_GLSL_version() || Cmdline_no_fbo || !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) ) { Cmdline_postprocess = 0; return; } // for ease of use we require support for non-power-of-2 textures in one // form or another: // - the NPOT extension // - GL version 2.0+ (which should work for non-reporting ATI cards since we don't use mipmaps) if ( !(Is_Extension_Enabled(OGL_ARB_TEXTURE_NON_POWER_OF_TWO) || (GL_version >= 20)) ) { Cmdline_postprocess = 0; return; } if ( !opengl_post_init_shaders() ) { mprintf((" Unable to initialize post-processing shaders! Disabling post-processing...\n\n")); Cmdline_postprocess = 0; return; } if ( !opengl_post_init_framebuffer() ) { mprintf((" Unable to initialize post-processing framebuffer! Disabling post-processing...\n\n")); Cmdline_postprocess = 0; return; } Post_initialized = 1; }
int get_num_mipmap_levels(int w, int h) { int size, levels = 0; // make sure we can and should generate mipmaps before trying to use them if ( !Cmdline_mipmap || !Is_Extension_Enabled(OGL_SGIS_GENERATE_MIPMAP) ) return 1; size = MAX(w, h); while (size > 0) { size >>= 1; levels++; } return (levels > 1) ? levels : 1; }
int batch_add_bitmap(int texture, int tmap_flags, vertex *pnt, int orient, float rad, float alpha, float depth) { if (texture < 0) { Int3(); return 1; } if ( tmap_flags & TMAP_FLAG_SOFT_QUAD && ( !Cmdline_softparticles || GLSL_version <= 120 ) ) { // don't render this as a soft particle if we don't support soft particles tmap_flags &= ~(TMAP_FLAG_SOFT_QUAD); } if ( GLSL_version > 120 && Cmdline_softparticles && !Cmdline_no_geo_sdr_effects && Is_Extension_Enabled(OGL_EXT_GEOMETRY_SHADER4) && (tmap_flags & TMAP_FLAG_VERTEX_GEN) ) { geometry_batch_add_bitmap(texture, tmap_flags, pnt, orient, rad, alpha, depth); return 0; } else if ( tmap_flags & TMAP_FLAG_VERTEX_GEN ) { tmap_flags &= ~(TMAP_FLAG_VERTEX_GEN); } batch_item *item = NULL; SCP_map<int, batch_item>::iterator it = geometry_map.find(texture); if ( !geometry_map.empty() && it != geometry_map.end() ) { item = &it->second; } else { item = &geometry_map[texture]; item->texture = texture; } Assertion( (item->laser == false), "Particle effect %s used as laser glow or laser bitmap\n", bm_get_filename(texture) ); item->tmap_flags = tmap_flags; item->alpha = alpha; item->batch.add_allocate(1); item->batch.draw_bitmap(pnt, orient, rad, depth); return 0; }
int gr_opengl_bm_set_render_target(int n, int face) { if ( !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) || Cmdline_no_fbo ) { return 0; } if (n == -1) { opengl_set_render_target(-1); return 1; } Assert( (n >= 0) && (n < MAX_BITMAPS) ); int is_static = (bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_STATIC); if ( opengl_set_render_target(n, face, is_static) ) { return 1; } return 0; }
void gr_opengl_bm_save_render_target(int n) { Assert( (n >= 0) && (n < MAX_BITMAPS) ); if ( !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) || Cmdline_no_fbo ) { return; } bitmap_entry *be = &bm_bitmaps[n]; bitmap *bmp = &be->bm; size_t rc = opengl_export_render_target( n, bmp->w, bmp->h, (bmp->true_bpp == 32), be->num_mipmaps, (ubyte*)bmp->data ); if (rc != be->mem_taken) { Int3(); return; } if (Cmdline_save_render_targets) { dds_save_image(bmp->w, bmp->h, bmp->true_bpp, be->num_mipmaps, (ubyte*)bmp->data, (bmp->flags & BMP_FLAG_CUBEMAP)); } }
void opengl_extensions_init() { opengl_get_extensions(); // if S3TC compression is found, then "GL_ARB_texture_compression" must be an extension Use_compressed_textures = Is_Extension_Enabled(OGL_EXT_TEXTURE_COMPRESSION_S3TC); Texture_compression_available = Is_Extension_Enabled(OGL_ARB_TEXTURE_COMPRESSION); // Swifty put this in, but it's not doing anything. Once he uses it, he can uncomment it. //int use_base_vertex = Is_Extension_Enabled(OGL_ARB_DRAW_ELEMENTS_BASE_VERTEX); //allow VBOs to be used if ( !Cmdline_nohtl && !Cmdline_novbo && Is_Extension_Enabled(OGL_ARB_VERTEX_BUFFER_OBJECT) ) { Use_VBOs = 1; } if ( !Cmdline_no_pbo && Is_Extension_Enabled(OGL_ARB_PIXEL_BUFFER_OBJECT) ) { Use_PBOs = 1; } // setup the best fog function found if ( !Fred_running ) { if ( Is_Extension_Enabled(OGL_EXT_FOG_COORD) ) { OGL_fogmode = 2; } else { OGL_fogmode = 1; } } // if we can't do cubemaps then turn off Cmdline_env if ( !(Is_Extension_Enabled(OGL_ARB_TEXTURE_CUBE_MAP) && Is_Extension_Enabled(OGL_ARB_TEXTURE_ENV_COMBINE)) ) { Cmdline_env = 0; } if ( !Cmdline_noglsl && Is_Extension_Enabled(OGL_ARB_SHADER_OBJECTS) && Is_Extension_Enabled(OGL_ARB_FRAGMENT_SHADER) && Is_Extension_Enabled(OGL_ARB_VERTEX_SHADER) ) { int ver = 0, major = 0, minor = 0; const char *glsl_ver = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION_ARB); sscanf(glsl_ver, "%d.%d", &major, &minor); ver = (major * 100) + minor; // SM 4.0 compatible or better if (ver >= 400) { Use_GLSL = 4; } // SM 3.0 compatible else if ( ver >= 130 ) { Use_GLSL = 3; } // SM 2.0 compatible else if (ver >= 120) { Use_GLSL = 2; } // we require GLSL 1.20 or higher else if (ver < 110) { Use_GLSL = 0; mprintf((" OpenGL Shading Language version %s is not sufficient to use GLSL mode in FSO. Defaulting to fixed-function renderer.\n", glGetString(GL_SHADING_LANGUAGE_VERSION_ARB) )); #ifdef NDEBUG popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, "GLSL support not available on this GPU. Disabling shader support and defaulting to fixed-function rendering.\n"); #endif } } // can't have this stuff without GLSL support if ( !Use_GLSL ) { Cmdline_normal = 0; Cmdline_height = 0; Cmdline_postprocess = 0; } if (Use_GLSL) { GLint max_texture_units; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &max_texture_units); // we need enough texture slots for this stuff to work if (max_texture_units < 6) { mprintf(( "Not enough texture units for height map support. We need at least 6, we found %d.\n", max_texture_units )); Cmdline_height = 0; } else if (max_texture_units < 5) { mprintf(( "Not enough texture units for height and normal map support. We need at least 5, we found %d.\n", max_texture_units )); Cmdline_normal = 0; Cmdline_height = 0; } else if (max_texture_units < 4) { mprintf(( "Not enough texture units found for GLSL support. We need at least 4, we found %d.\n", max_texture_units )); Use_GLSL = 0; } } }
void opengl_extensions_init() { opengl_get_extensions(); // if S3TC compression is found, then "GL_ARB_texture_compression" must be an extension Use_compressed_textures = Is_Extension_Enabled(OGL_EXT_TEXTURE_COMPRESSION_S3TC); Texture_compression_available = Is_Extension_Enabled(OGL_ARB_TEXTURE_COMPRESSION); // Swifty put this in, but it's not doing anything. Once he uses it, he can uncomment it. //int use_base_vertex = Is_Extension_Enabled(OGL_ARB_DRAW_ELEMENTS_BASE_VERTEX); //allow VBOs to be used if ( !Cmdline_nohtl && !Cmdline_novbo && Is_Extension_Enabled(OGL_ARB_VERTEX_BUFFER_OBJECT) ) { Use_VBOs = 1; } if ( !Cmdline_no_pbo && Is_Extension_Enabled(OGL_ARB_PIXEL_BUFFER_OBJECT) ) { Use_PBOs = 1; } // setup the best fog function found if ( !Fred_running ) { if ( Is_Extension_Enabled(OGL_EXT_FOG_COORD) ) { OGL_fogmode = 2; } else { OGL_fogmode = 1; } } // if we can't do cubemaps then turn off Cmdline_env if ( !(Is_Extension_Enabled(OGL_ARB_TEXTURE_CUBE_MAP) && Is_Extension_Enabled(OGL_ARB_TEXTURE_ENV_COMBINE)) ) { Cmdline_env = 0; } if ( !(Is_Extension_Enabled(OGL_EXT_GEOMETRY_SHADER4) && Is_Extension_Enabled(OGL_EXT_TEXTURE_ARRAY) && Is_Extension_Enabled(OGL_ARB_DRAW_ELEMENTS_BASE_VERTEX)) ) { Cmdline_shadow_quality = 0; mprintf((" No hardware support for shadow mapping. Shadows will be disabled. \n")); } if ( !Cmdline_noglsl && Is_Extension_Enabled(OGL_ARB_SHADER_OBJECTS) && Is_Extension_Enabled(OGL_ARB_FRAGMENT_SHADER) && Is_Extension_Enabled(OGL_ARB_VERTEX_SHADER) ) { int ver = 0, major = 0, minor = 0; const char *glsl_ver = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); sscanf(glsl_ver, "%d.%d", &major, &minor); ver = (major * 100) + minor; GLSL_version = ver; // we require a minimum GLSL version if (!is_minimum_GLSL_version()) { mprintf((" OpenGL Shading Language version %s is not sufficient to use GLSL mode in FSO. Defaulting to fixed-function renderer.\n", glGetString(GL_SHADING_LANGUAGE_VERSION) )); } } // can't have this stuff without GLSL support if ( !is_minimum_GLSL_version() ) { Cmdline_normal = 0; Cmdline_height = 0; Cmdline_postprocess = 0; Cmdline_shadow_quality = 0; Cmdline_no_deferred_lighting = 1; } if ( GLSL_version < 120 || !Is_Extension_Enabled(OGL_EXT_FRAMEBUFFER_OBJECT) || !Is_Extension_Enabled(OGL_ARB_FLOATING_POINT_TEXTURES) ) { mprintf((" No hardware support for deferred lighting. Deferred lighting will be disabled. \n")); Cmdline_no_deferred_lighting = 1; Cmdline_no_batching = true; } if (is_minimum_GLSL_version()) { GLint max_texture_units; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &max_texture_units); // we need enough texture slots for this stuff to work if (max_texture_units < 6) { mprintf(( "Not enough texture units for height map support. We need at least 6, we found %d.\n", max_texture_units )); Cmdline_height = 0; } else if (max_texture_units < 5) { mprintf(( "Not enough texture units for height and normal map support. We need at least 5, we found %d.\n", max_texture_units )); Cmdline_normal = 0; Cmdline_height = 0; } else if (max_texture_units < 4) { mprintf(( "Not enough texture units found for GLSL support. We need at least 4, we found %d.\n", max_texture_units )); GLSL_version = 0; } } }
/** * Compiles a new shader, and creates an opengl_shader_t that will be put into the GL_shader vector * if compilation is successful. * * @param sdr Identifier defined with the program we wish to compile * @param flags Combination of SDR_* flags */ int opengl_compile_shader(shader_type sdr, uint flags) { int sdr_index = -1; int empty_idx; opengl_shader_t new_shader; Assert(sdr < NUM_SHADER_TYPES); opengl_shader_type_t *sdr_info = &GL_shader_types[sdr]; mprintf(("Compiling new shader:\n")); mprintf((" %s\n", sdr_info->description)); // figure out if the variant requested needs a geometry shader bool use_geo_sdr = false; // do we even have a geometry shader? if ( sdr_info->geo != NULL ) { for (int i = 0; i < GL_num_shader_variants; ++i) { opengl_shader_variant_t *variant = &GL_shader_variants[i]; if (variant->type_id == sdr && flags & variant->flag && variant->use_geometry_sdr) { use_geo_sdr = true; break; } } } auto vertex_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->vert, flags); auto fragment_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->frag, flags); SCP_vector<SCP_string> geom_content; if ( use_geo_sdr ) { if (!Is_Extension_Enabled(OGL_EXT_GEOMETRY_SHADER4)) { return -1; } // read geometry shader geom_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->geo, flags); Current_geo_sdr_params = &sdr_info->geo_sdr_info; } new_shader.program_id = opengl_shader_create(vertex_content, fragment_content, geom_content); if (!new_shader.program_id) { return -1; } new_shader.shader = sdr_info->type_id; new_shader.flags = flags; opengl_shader_set_current(&new_shader); // initialize uniforms and attributes for ( int i = 0; i < sdr_info->num_uniforms; ++i ) { opengl_shader_init_uniform( sdr_info->uniforms[i] ); } for (int i = 0; i < sdr_info->num_attributes; ++i) { opengl_shader_init_attribute(sdr_info->attributes[i]); } // if this shader is POST_PROCESS_MAIN, hack in the user-defined flags if ( sdr_info->type_id == SDR_TYPE_POST_PROCESS_MAIN ) { opengl_post_init_uniforms(flags); } mprintf(("Shader Variant Features:\n")); // initialize all uniforms and attributes that are specific to this variant for ( int i = 0; i < GL_num_shader_variants; ++i ) { opengl_shader_variant_t &variant = GL_shader_variants[i]; if ( sdr_info->type_id == variant.type_id && variant.flag & flags ) { for (int j = 0; j < variant.num_uniforms; ++j) { opengl_shader_init_uniform(variant.uniforms[j]); } for (int j = 0; j < variant.num_attributes; ++j) { opengl_shader_init_attribute(variant.attributes[j]); } mprintf((" %s\n", variant.description)); } } opengl_shader_set_current(); // add it to our list of embedded shaders // see if we have empty shader slots empty_idx = -1; for ( int i = 0; i < (int)GL_shader.size(); ++i ) { if ( GL_shader[i].shader == NUM_SHADER_TYPES ) { empty_idx = i; break; } } // then insert it at an empty slot or at the end if ( empty_idx >= 0 ) { GL_shader[empty_idx] = new_shader; sdr_index = empty_idx; } else { sdr_index = GL_shader.size(); GL_shader.push_back(new_shader); } return sdr_index; }