/** * Compile the deferred light shader and the clear shader. */ void opengl_shader_compile_deferred_light_shader() { bool in_error = false; int sdr_handle = gr_opengl_maybe_create_shader(SDR_TYPE_DEFERRED_LIGHTING, 0); if ( sdr_handle >= 0 ) { opengl_shader_set_current(sdr_handle); Current_shader->program->Uniforms.setUniformi("ColorBuffer", 0); Current_shader->program->Uniforms.setUniformi("NormalBuffer", 1); Current_shader->program->Uniforms.setUniformi("PositionBuffer", 2); Current_shader->program->Uniforms.setUniformi("SpecBuffer", 3); Current_shader->program->Uniforms.setUniformf("invScreenWidth", 1.0f / gr_screen.max_w); Current_shader->program->Uniforms.setUniformf("invScreenHeight", 1.0f / gr_screen.max_h); Current_shader->program->Uniforms.setUniformf("specFactor", Cmdline_ogl_spec); } else { opengl_shader_set_current(); mprintf(("Failed to compile deferred lighting shader!\n")); in_error = true; } if ( gr_opengl_maybe_create_shader(SDR_TYPE_DEFERRED_CLEAR, 0) < 0 ) { mprintf(("Failed to compile deferred lighting buffer clear shader!\n")); in_error = true; } if ( in_error ) { mprintf((" Shader in_error! Disabling deferred lighting!\n")); Cmdline_no_deferred_lighting = 1; } }
void opengl_shader_compile_passthrough_shader() { mprintf(("Compiling passthrough shader...\n")); int sdr_handle = gr_opengl_maybe_create_shader(SDR_TYPE_PASSTHROUGH_RENDER, 0); opengl_shader_set_current(sdr_handle); //Hardcoded Uniforms Current_shader->program->Uniforms.setUniformi("baseMap", 0); Current_shader->program->Uniforms.setUniformi("clipEnabled", 0); opengl_shader_set_current(); }
/** * 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 * @param replacement_idx The index of the shader this replaces. If -1, the newly compiled shader will be appended to the GL_shader vector * or inserted at the first available empty slot */ int opengl_compile_shader(shader_type sdr, uint flags) { GR_DEBUG_SCOPE("Creating new shader"); int sdr_index = -1; int empty_idx; opengl_shader_t new_shader; Assert(sdr < NUM_SHADER_TYPES); opengl_compile_shader_actual(sdr, flags, new_shader); 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] = std::move(new_shader); sdr_index = empty_idx; } else { sdr_index = (int)GL_shader.size(); GL_shader.push_back(std::move(new_shader)); } return sdr_index; }
void opengl_shader_set_current(int handle) { Assert(handle >= 0); Assert(handle < (int)GL_shader.size()); opengl_shader_set_current(&GL_shader[handle]); }
void opengl_post_lightshafts() { opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_LIGHTSHAFTS, 0)); float x, y; // should we even be here? if ( !Game_subspace_effect && ls_on && !ls_force_off ) { int n_lights = light_get_global_count(); for ( int idx = 0; idx<n_lights; idx++ ) { vec3d light_dir; vec3d local_light_dir; light_get_global_dir(&light_dir, idx); vm_vec_rotate(&local_light_dir, &light_dir, &Eye_matrix); if ( !stars_sun_has_glare(idx) ) { continue; } float dot; if ( (dot = vm_vec_dot(&light_dir, &Eye_matrix.vec.fvec)) > 0.7f ) { 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 y = asinf(vm_vec_dot(&light_dir, &Eye_matrix.vec.uvec)) / PI*1.5f*gr_screen.clip_aspect + 0.5f; Current_shader->program->Uniforms.setUniform2f("sun_pos", x, y); Current_shader->program->Uniforms.setUniformi("scene", 0); Current_shader->program->Uniforms.setUniformi("cockpit", 1); Current_shader->program->Uniforms.setUniformf("density", ls_density); Current_shader->program->Uniforms.setUniformf("falloff", ls_falloff); Current_shader->program->Uniforms.setUniformf("weight", ls_weight); Current_shader->program->Uniforms.setUniformf("intensity", Sun_spot * ls_intensity); Current_shader->program->Uniforms.setUniformf("cp_intensity", Sun_spot * ls_cpintensity); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_depth_texture); GL_state.Texture.SetActiveUnit(1); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Cockpit_depth_texture); GL_state.Blend(GL_TRUE); GL_state.SetAlphaBlendMode(ALPHA_BLEND_ADDITIVE); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Blend(GL_FALSE); break; } } } if ( zbuffer_saved ) { zbuffer_saved = false; gr_zbuffer_set(GR_ZBUFF_FULL); glClear(GL_DEPTH_BUFFER_BIT); gr_zbuffer_set(GR_ZBUFF_NONE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, Scene_depth_texture, 0); } }
void opengl_post_pass_fxaa() { //If the preset changed, recompile the shader if (Fxaa_preset_last_frame != Cmdline_fxaa_preset) { recompile_fxaa_shader(); } // We only want to draw to ATTACHMENT0 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // Do a prepass to convert the main shaders' RGBA output into RGBL opengl_shader_set_current( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA_PREPASS, 0) ); // basic/default uniforms GL_state.Uniform.setUniformi( "tex", 0 ); vglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Scene_luminance_texture, 0); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_color_texture); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Texture.Disable(); // set and configure post shader .. opengl_shader_set_current( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA, 0) ); vglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Scene_color_texture, 0); // basic/default uniforms GL_state.Uniform.setUniformi( "tex0", 0 ); GL_state.Uniform.setUniformf( "rt_w", static_cast<float>(Post_texture_width)); GL_state.Uniform.setUniformf( "rt_h", static_cast<float>(Post_texture_height)); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_luminance_texture); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Texture.Disable(); opengl_shader_set_current(); }
void gr_opengl_clear_states() { gr_zbias(0); gr_zbuffer_set(ZBUFFER_TYPE_READ); gr_set_cull(0); gr_set_fill_mode(GR_FILL_MODE_SOLID); opengl_shader_set_current(); }
void gr_opengl_clear_states() { GL_state.Texture.DisableAll(); gr_zbias(0); gr_zbuffer_set(ZBUFFER_TYPE_READ); gr_set_cull(0); gr_set_fill_mode(GR_FILL_MODE_SOLID); gr_reset_lighting(); gr_set_lighting(false, false); opengl_shader_set_current(); }
void opengl_tnl_set_material(material* material_info, bool set_base_map) { int shader_handle = material_info->get_shader_handle(); int base_map = material_info->get_texture_map(TM_BASE_TYPE); vec4 clr = material_info->get_color(); Assert(shader_handle >= 0); opengl_shader_set_current(shader_handle); if ( Current_shader->shader == SDR_TYPE_PASSTHROUGH_RENDER ) { opengl_shader_set_passthrough(base_map >= 0, material_info->get_texture_type() == TCACHE_TYPE_AABITMAP, &clr, material_info->get_color_scale()); } GL_state.SetAlphaBlendMode(material_info->get_blend_mode()); GL_state.SetZbufferType(material_info->get_depth_mode()); gr_set_cull(material_info->get_cull_mode() ? 1 : 0); gr_zbias(material_info->get_depth_bias()); gr_set_fill_mode(material_info->get_fill_mode()); material::fog &fog_params = material_info->get_fog(); if ( fog_params.enabled ) { gr_fog_set(GR_FOGMODE_FOG, fog_params.r, fog_params.g, fog_params.b, fog_params.dist_near, fog_params.dist_far); } else { gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0); } gr_set_texture_addressing(material_info->get_texture_addressing()); material::clip_plane &clip_params = material_info->get_clip_plane(); if ( clip_params.enabled ) { gr_opengl_set_clip_plane(&clip_params.normal, &clip_params.position); } else { gr_opengl_set_clip_plane(NULL, NULL); } if ( set_base_map && base_map >= 0 ) { float u_scale, v_scale; if ( !gr_opengl_tcache_set(base_map, material_info->get_texture_type(), &u_scale, &v_scale) ) { mprintf(("WARNING: Error setting bitmap texture (%i)!\n", base_map)); } } }
void opengl_post_pass_tonemap() { opengl_shader_set_current( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_TONEMAPPING, 0) ); Current_shader->program->Uniforms.setUniformi("tex", 0); Current_shader->program->Uniforms.setUniformf("exposure", 4.0f); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Scene_ldr_texture, 0); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_color_texture); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); }
void gr_opengl_clear_states() { if ( GL_version >= 30 ) { glBindVertexArray(GL_vao); } gr_zbias(0); gr_zbuffer_set(ZBUFFER_TYPE_READ); gr_set_cull(0); gr_set_fill_mode(GR_FILL_MODE_SOLID); gr_reset_lighting(); gr_set_lighting(false, false); opengl_shader_set_current(); }
void opengl_shader_set_passthrough(bool textured) { opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_PASSTHROUGH_RENDER, 0)); if ( textured ) { Current_shader->program->Uniforms.setUniformi("noTexturing", 0); } else { Current_shader->program->Uniforms.setUniformi("noTexturing", 1); } Current_shader->program->Uniforms.setUniformi("alphaTexture", 0); Current_shader->program->Uniforms.setUniformi("srgb", High_dynamic_range ? 1 : 0); Current_shader->program->Uniforms.setUniformf("intensity", 1.0f); Current_shader->program->Uniforms.setUniformf("alphaThreshold", GL_alpha_threshold); Current_shader->program->Uniforms.setUniform4f("color", 1.0f, 1.0f, 1.0f, 1.0f); Current_shader->program->Uniforms.setUniformMatrix4f("modelViewMatrix", gr_model_view_matrix); Current_shader->program->Uniforms.setUniformMatrix4f("projMatrix", gr_projection_matrix); }
/** * 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; }
void opengl_compile_shader_actual(shader_type sdr, const uint &flags, opengl_shader_t &new_shader) { opengl_shader_type_t *sdr_info = &GL_shader_types[sdr]; Assert(sdr_info->type_id == 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 vert_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->vert, flags, use_geo_sdr); auto frag_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->frag, flags, use_geo_sdr); SCP_vector<SCP_string> geom_content; if (use_geo_sdr) { // read geometry shader geom_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->geo, flags, use_geo_sdr); } auto shader_hash = get_shader_hash(vert_content, geom_content, frag_content); std::unique_ptr<opengl::ShaderProgram> program(new opengl::ShaderProgram(sdr_info->description)); if (!load_cached_shader_binary(program.get(), shader_hash)) { GR_DEBUG_SCOPE("Compiling shader code"); try { program->addShaderCode(opengl::STAGE_VERTEX, sdr_info->vert, vert_content); program->addShaderCode(opengl::STAGE_FRAGMENT, sdr_info->frag, frag_content); if (use_geo_sdr) { program->addShaderCode(opengl::STAGE_GEOMETRY, sdr_info->geo, geom_content); } for (size_t i = 0; i < GL_vertex_attrib_info.size(); ++i) { // Check that the enum values match the position in the vector to make accessing that information more efficient Assertion(GL_vertex_attrib_info[i].attribute_id == (int)i, "Mistmatch between enum values and attribute vector detected!"); // assign vert attribute binding locations before we link the shader glBindAttribLocation(program->getShaderHandle(), (GLint)i, GL_vertex_attrib_info[i].name.c_str()); } // bind fragment data locations before we link the shader glBindFragDataLocation(program->getShaderHandle(), 0, "fragOut0"); glBindFragDataLocation(program->getShaderHandle(), 1, "fragOut1"); glBindFragDataLocation(program->getShaderHandle(), 2, "fragOut2"); glBindFragDataLocation(program->getShaderHandle(), 3, "fragOut3"); glBindFragDataLocation(program->getShaderHandle(), 4, "fragOut4"); if (do_shader_caching()) { // Enable shader caching glProgramParameteri(program->getShaderHandle(), GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); } program->linkProgram(); } catch (const std::exception&) { // Since all shaders are required a compilation failure is a fatal error Error(LOCATION, "A shader failed to compile! Check the debug log for more information."); } cache_program_binary(program->getShaderHandle(), shader_hash); } new_shader.shader = sdr_info->type_id; new_shader.flags = flags; new_shader.program = std::move(program); opengl_shader_set_current(&new_shader); // initialize the attributes for (auto& attr : sdr_info->attributes) { new_shader.program->initAttribute(GL_vertex_attrib_info[attr].name, GL_vertex_attrib_info[attr].attribute_id, GL_vertex_attrib_info[attr].default_value); } for (auto& uniform_block : GL_uniform_blocks) { auto blockIndex = glGetUniformBlockIndex(new_shader.program->getShaderHandle(), uniform_block.name); if (blockIndex != GL_INVALID_INDEX) { glUniformBlockBinding(new_shader.program->getShaderHandle(), blockIndex, static_cast<GLuint>(uniform_block.block_type)); } } 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 (auto& attr : variant.attributes) { auto& attr_info = GL_vertex_attrib_info[attr]; new_shader.program->initAttribute(attr_info.name, attr_info.attribute_id, attr_info.default_value); } mprintf((" %s\n", variant.description)); } } opengl_set_default_uniforms(new_shader); }
void opengl_tnl_set_material(material* material_info, bool set_base_map, bool set_clipping) { int shader_handle = material_info->get_shader_handle(); int base_map = material_info->get_texture_map(TM_BASE_TYPE); vec4 clr = material_info->get_color(); Assert(shader_handle >= 0); opengl_shader_set_current(shader_handle); if (material_info->has_buffer_blend_modes()) { Assertion(GLAD_GL_ARB_draw_buffers_blend != 0, "Buffer blend modes are not supported at the moment! Query the capability before using this feature."); auto enable_blend = false; for (auto i = 0; i < (int) material::NUM_BUFFER_BLENDS; ++i) { auto mode = material_info->get_blend_mode(i); GL_state.SetAlphaBlendModei(i, mode); enable_blend = enable_blend || mode != ALPHA_BLEND_NONE; } GL_state.Blend(enable_blend ? GL_TRUE : GL_FALSE); } else { GL_state.SetAlphaBlendMode(material_info->get_blend_mode()); } GL_state.SetZbufferType(material_info->get_depth_mode()); gr_set_cull(material_info->get_cull_mode() ? 1 : 0); gr_zbias(material_info->get_depth_bias()); gr_set_fill_mode(material_info->get_fill_mode()); gr_set_texture_addressing(material_info->get_texture_addressing()); if (set_clipping) { // Only set the clipping state if explicitly requested by the caller to avoid unnecessary state changes auto& clip_params = material_info->get_clip_plane(); if (!clip_params.enabled) { GL_state.ClipDistance(0, false); } else { Assertion(Current_shader != NULL && (Current_shader->shader == SDR_TYPE_MODEL || Current_shader->shader == SDR_TYPE_PASSTHROUGH_RENDER || Current_shader->shader == SDR_TYPE_DEFAULT_MATERIAL), "Clip planes are not supported by this shader!"); GL_state.ClipDistance(0, true); } } GL_state.StencilMask(material_info->get_stencil_mask()); auto& stencilFunc = material_info->get_stencil_func(); GL_state.StencilFunc(convertComparisionFunction(stencilFunc.compare), stencilFunc.ref, stencilFunc.mask); auto& frontStencilOp = material_info->get_front_stencil_op(); GL_state.StencilOpSeparate(GL_FRONT, convertStencilOp(frontStencilOp.stencilFailOperation), convertStencilOp(frontStencilOp.depthFailOperation), convertStencilOp(frontStencilOp.successOperation)); auto& backStencilOp = material_info->get_back_stencil_op(); GL_state.StencilOpSeparate(GL_BACK, convertStencilOp(backStencilOp.stencilFailOperation), convertStencilOp(backStencilOp.depthFailOperation), convertStencilOp(backStencilOp.successOperation)); GL_state.StencilTest(material_info->is_stencil_enabled() ? GL_TRUE : GL_FALSE); auto& color_mask = material_info->get_color_mask(); GL_state.ColorMask(color_mask.x, color_mask.y, color_mask.z, color_mask.w); // This is only needed for the passthrough shader uint32_t array_index = 0; if ( set_base_map && base_map >= 0 ) { float u_scale, v_scale; if ( !gr_opengl_tcache_set(base_map, material_info->get_texture_type(), &u_scale, &v_scale, &array_index) ) { mprintf(("WARNING: Error setting bitmap texture (%i)!\n", base_map)); } } if ( Current_shader->shader == SDR_TYPE_DEFAULT_MATERIAL ) { opengl_shader_set_default_material(base_map >= 0, material_info->get_texture_type() == TCACHE_TYPE_AABITMAP, &clr, material_info->get_color_scale(), array_index, material_info->get_clip_plane()); } }
void gr_opengl_post_process_end() { // state switch just the once (for bloom pass and final render-to-screen) GLboolean depth = GL_state.DepthTest(GL_FALSE); GLboolean depth_mask = GL_state.DepthMask(GL_FALSE); GLboolean lighting = GL_state.Lighting(GL_FALSE); GLboolean blend = GL_state.Blend(GL_FALSE); GLboolean cull = GL_state.CullFace(GL_FALSE); GL_state.Texture.SetShaderMode(GL_TRUE); // Do FXAA if (Cmdline_fxaa && !fxaa_unavailable && !GL_rendering_to_texture) { opengl_post_pass_fxaa(); } opengl_shader_set_current( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_LIGHTSHAFTS, 0) ); float x,y; // should we even be here? if (!Game_subspace_effect && ls_on && !ls_force_off) { int n_lights = light_get_global_count(); for(int idx=0; idx<n_lights; idx++) { vec3d light_dir; vec3d local_light_dir; light_get_global_dir(&light_dir, idx); vm_vec_rotate(&local_light_dir, &light_dir, &Eye_matrix); if (!stars_sun_has_glare(idx)) continue; float dot; if((dot=vm_vec_dot( &light_dir, &Eye_matrix.vec.fvec )) > 0.7f) { 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 y = asinf(vm_vec_dot( &light_dir, &Eye_matrix.vec.uvec ))/PI*1.5f*gr_screen.clip_aspect+0.5f; GL_state.Uniform.setUniform2f( "sun_pos", x, y); GL_state.Uniform.setUniformi( "scene", 0); GL_state.Uniform.setUniformi( "cockpit", 1); GL_state.Uniform.setUniformf( "density", ls_density); GL_state.Uniform.setUniformf( "falloff", ls_falloff); GL_state.Uniform.setUniformf( "weight", ls_weight); GL_state.Uniform.setUniformf( "intensity", Sun_spot * ls_intensity); GL_state.Uniform.setUniformf( "cp_intensity", Sun_spot * ls_cpintensity); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_depth_texture); GL_state.Texture.SetActiveUnit(1); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Cockpit_depth_texture); GL_state.Color(255, 255, 255, 255); GL_state.Blend(GL_TRUE); GL_state.SetAlphaBlendMode(ALPHA_BLEND_ADDITIVE); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Blend(GL_FALSE); break; } } } if(zbuffer_saved) { zbuffer_saved = false; gr_zbuffer_set(GR_ZBUFF_FULL); glClear(GL_DEPTH_BUFFER_BIT); gr_zbuffer_set(GR_ZBUFF_NONE); vglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, Scene_depth_texture, 0); } // do bloom, hopefully ;) bool bloomed = opengl_post_pass_bloom(); // do tone mapping opengl_post_pass_tonemap(); // now write to the on-screen buffer vglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, opengl_get_rtt_framebuffer()); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); GL_state.Color(255, 255, 255, 255); // set and configure post shader ... int flags = 0; for ( int i = 0; i < (int)Post_effects.size(); i++) { if (Post_effects[i].always_on) { flags |= (1 << i); } } int post_sdr_handle = Post_active_shader_index; if ( post_sdr_handle < 0 ) { // no active shader index? use the always on shader. post_sdr_handle = gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_MAIN, flags); } opengl_shader_set_current(post_sdr_handle); // basic/default uniforms GL_state.Uniform.setUniformi( "tex", 0 ); GL_state.Uniform.setUniformi( "depth_tex", 2); GL_state.Uniform.setUniformf( "timer", static_cast<float>(timer_get_milliseconds() % 100 + 1) ); for (size_t idx = 0; idx < Post_effects.size(); idx++) { if ( GL_shader[post_sdr_handle].flags & (1<<idx) ) { const char *name = Post_effects[idx].uniform_name.c_str(); float value = Post_effects[idx].intensity; GL_state.Uniform.setUniformf( name, value); } } // bloom uniforms, but only if we did the bloom if (bloomed) { float intensity = MIN((float)Cmdline_bloom_intensity, 200.0f) * 0.01f; if (Neb2_render_mode != NEB2_RENDER_NONE) { // we need less intensity for full neb missions, so cut it by 30% intensity /= 3.0f; } //GL_state.Uniform.setUniformf( "bloom_intensity", intensity ); GL_state.Uniform.setUniformf( "bloom_intensity", 0.0f ); GL_state.Uniform.setUniformi( "levels" , MAX_MIP_BLUR_LEVELS ); GL_state.Uniform.setUniformi( "bloomed", 1 ); GL_state.Texture.SetActiveUnit(1); GL_state.Texture.SetTarget(GL_TEXTURE_2D); //GL_state.Texture.Enable(Post_bloom_texture_id[2]); GL_state.Texture.Enable(Bloom_textures[0]); } else GL_state.Uniform.setUniformf( "bloom_intensity", 0.0f ); // now render it to the screen ... vglBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); //GL_state.Texture.Enable(Scene_color_texture); GL_state.Texture.Enable(Scene_ldr_texture); GL_state.Texture.SetActiveUnit(2); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_depth_texture); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); //Shadow Map debug window //#define SHADOW_DEBUG #ifdef SHADOW_DEBUG opengl_shader_set_current( &GL_post_shader[8] ); GL_state.Texture.SetActiveUnit(0); // GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.SetTarget(GL_TEXTURE_2D_ARRAY); // GL_state.Texture.Enable(Shadow_map_depth_texture); extern GLuint Shadow_map_texture; extern GLuint Post_shadow_texture_id; GL_state.Texture.Enable(Shadow_map_texture); vglUniform1iARB( opengl_shader_get_uniform("shadow_map"), 0); vglUniform1iARB( opengl_shader_get_uniform("index"), 0); //opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, Scene_texture_u_scale, Scene_texture_u_scale); //opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.5f); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 1.0f, 1.0f); vglUniform1iARB( opengl_shader_get_uniform("index"), 1); //opengl_draw_textured_quad(-1.0f, -0.5f, 0.5f, 0.0f, -0.5f, 0.0f, 0.75f, 0.25f); opengl_draw_textured_quad(-1.0f, -0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 1.0f); vglUniform1iARB( opengl_shader_get_uniform("index"), 2); opengl_draw_textured_quad(-0.5f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 1.0f, 1.0f); vglUniform1iARB( opengl_shader_get_uniform("index"), 3); opengl_draw_textured_quad(-0.5f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 1.0f, 1.0f); opengl_shader_set_current(); #endif /*GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_depth_texture); */ // Done! /*GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_effect_texture); opengl_draw_textured_quad(0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_normal_texture); opengl_draw_textured_quad(-1.0f, -0.0f, 0.0f, 0.0f, 0.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_specular_texture); opengl_draw_textured_quad(0.0f, -0.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); */ GL_state.Texture.SetActiveUnit(2); GL_state.Texture.Disable(); GL_state.Texture.SetActiveUnit(1); GL_state.Texture.Disable(); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.Disable(); GL_state.Texture.SetShaderMode(GL_FALSE); // reset state GL_state.DepthTest(depth); GL_state.DepthMask(depth_mask); GL_state.Lighting(lighting); GL_state.Blend(blend); GL_state.CullFace(cull); opengl_shader_set_current(); Post_in_frame = false; }
/** * Compiles a new shader, and creates an opengl_shader_t that will be put into the GL_shader vector * if compilation is successful. * This function is used for main (i.e. model rendering) and particle shaders, post processing shaders use their own infrastructure * * @param flags Combination of SDR_* flags */ void opengl_compile_main_shader(int flags) { char *vert = NULL, *frag = NULL; mprintf(("Compiling new shader:\n")); bool in_error = false; opengl_shader_t new_shader; // choose appropriate files char vert_name[NAME_LENGTH]; char frag_name[NAME_LENGTH]; if (flags & SDR_FLAG_SOFT_QUAD) { strcpy_s( vert_name, "soft-v.sdr"); strcpy_s( frag_name, "soft-f.sdr"); } else { strcpy_s( vert_name, "main-v.sdr"); strcpy_s( frag_name, "main-f.sdr"); } // read vertex shader if ( (vert = opengl_load_shader(vert_name, flags)) == NULL ) { in_error = true; goto Done; } // read fragment shader if ( (frag = opengl_load_shader(frag_name, flags)) == NULL ) { in_error = true; goto Done; } Verify( vert != NULL ); Verify( frag != NULL ); new_shader.program_id = opengl_shader_create(vert, frag); if ( !new_shader.program_id ) { in_error = true; goto Done; } new_shader.flags = flags; opengl_shader_set_current( &new_shader ); mprintf(("Shader features:\n")); //Init all the uniforms if (new_shader.flags & SDR_FLAG_SOFT_QUAD) { for (int j = 0; j < Particle_shader_flag_references; j++) { if (new_shader.flags == GL_Uniform_Reference_Particle[j].flag) { int k; // Equality check needed because the combination of SDR_FLAG_SOFT_QUAD and SDR_FLAG_DISTORTION define something very different // than just SDR_FLAG_SOFT_QUAD alone for (k = 0; k < GL_Uniform_Reference_Particle[j].num_uniforms; k++) { opengl_shader_init_uniform( GL_Uniform_Reference_Particle[j].uniforms[k] ); } for (k = 0; k < GL_Uniform_Reference_Particle[j].num_attributes; k++) { opengl_shader_init_attribute( GL_Uniform_Reference_Particle[j].attributes[k] ); } mprintf((" %s\n", GL_Uniform_Reference_Particle[j].name)); } } } else { for (int j = 0; j < Main_shader_flag_references; j++) { if (new_shader.flags & GL_Uniform_Reference_Main[j].flag) { if (GL_Uniform_Reference_Main[j].num_uniforms > 0) { for (int k = 0; k < GL_Uniform_Reference_Main[j].num_uniforms; k++) { opengl_shader_init_uniform( GL_Uniform_Reference_Main[j].uniforms[k] ); } } if (GL_Uniform_Reference_Main[j].num_attributes > 0) { for (int k = 0; k < GL_Uniform_Reference_Main[j].num_attributes; k++) { opengl_shader_init_attribute( GL_Uniform_Reference_Main[j].attributes[k] ); } } mprintf((" %s\n", GL_Uniform_Reference_Main[j].name)); } } } opengl_shader_set_current(); // add it to our list of embedded shaders GL_shader.push_back( new_shader ); Done: if (vert != NULL) { vm_free(vert); vert = NULL; } if (frag != NULL) { vm_free(frag); frag = NULL; } if (in_error) { // shut off relevant usage things ... bool dealt_with = false; if (flags & SDR_FLAG_HEIGHT_MAP) { mprintf((" Shader in_error! Disabling height maps!\n")); Cmdline_height = 0; dealt_with = true; } if (flags & SDR_FLAG_NORMAL_MAP) { mprintf((" Shader in_error! Disabling normal maps and height maps!\n")); Cmdline_height = 0; Cmdline_normal = 0; dealt_with = true; } if (!dealt_with) { if (flags == 0) { mprintf((" Shader in_error! Disabling GLSL!\n")); Use_GLSL = 0; Cmdline_height = 0; Cmdline_normal = 0; GL_shader.clear(); } else { // We died on a lighting shader, probably due to instruction count. // Drop down to a special var that will use fixed-function rendering // but still allow for post-processing to work mprintf((" Shader in_error! Disabling GLSL model rendering!\n")); Use_GLSL = 1; Cmdline_height = 0; Cmdline_normal = 0; } } } }
void gr_opengl_post_process_end() { // state switch just the once (for bloom pass and final render-to-screen) GLboolean depth = GL_state.DepthTest(GL_FALSE); GLboolean depth_mask = GL_state.DepthMask(GL_FALSE); GLboolean blend = GL_state.Blend(GL_FALSE); GLboolean cull = GL_state.CullFace(GL_FALSE); GL_state.Texture.SetShaderMode(GL_TRUE); // do bloom, hopefully ;) opengl_post_pass_bloom(); // do tone mapping opengl_post_pass_tonemap(); // Do FXAA if (Cmdline_fxaa && !fxaa_unavailable && !GL_rendering_to_texture) { opengl_post_pass_fxaa(); } // render lightshafts opengl_post_lightshafts(); // now write to the on-screen buffer glBindFramebuffer(GL_FRAMEBUFFER, opengl_get_rtt_framebuffer()); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // set and configure post shader ... int flags = 0; for ( int i = 0; i < (int)Post_effects.size(); i++) { if (Post_effects[i].always_on) { flags |= (1 << i); } } int post_sdr_handle = Post_active_shader_index; if ( post_sdr_handle < 0 ) { // no active shader index? use the always on shader. post_sdr_handle = gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_MAIN, flags); } opengl_shader_set_current(post_sdr_handle); // basic/default uniforms Current_shader->program->Uniforms.setUniformi( "tex", 0 ); Current_shader->program->Uniforms.setUniformi( "depth_tex", 1); Current_shader->program->Uniforms.setUniformf( "timer", static_cast<float>(timer_get_milliseconds() % 100 + 1) ); for (size_t idx = 0; idx < Post_effects.size(); idx++) { if ( GL_shader[post_sdr_handle].flags & (1<<idx) ) { const char *name = Post_effects[idx].uniform_name.c_str(); float value = Post_effects[idx].intensity; Current_shader->program->Uniforms.setUniformf( name, value); } } // now render it to the screen ... glBindFramebuffer(GL_FRAMEBUFFER,0); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); //GL_state.Texture.Enable(Scene_color_texture); GL_state.Texture.Enable(Scene_ldr_texture); GL_state.Texture.SetActiveUnit(1); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_depth_texture); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); //Shadow Map debug window //#define SHADOW_DEBUG #ifdef SHADOW_DEBUG opengl_shader_set_current( &GL_post_shader[8] ); GL_state.Texture.SetActiveUnit(0); // GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.SetTarget(GL_TEXTURE_2D_ARRAY); // GL_state.Texture.Enable(Shadow_map_depth_texture); extern GLuint Shadow_map_texture; extern GLuint Post_shadow_texture_id; GL_state.Texture.Enable(Shadow_map_texture); glUniform1iARB( opengl_shader_get_uniform("shadow_map"), 0); glUniform1iARB( opengl_shader_get_uniform("index"), 0); //opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, Scene_texture_u_scale, Scene_texture_u_scale); //opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.5f); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 1.0f, 1.0f); glUniform1iARB( opengl_shader_get_uniform("index"), 1); //opengl_draw_textured_quad(-1.0f, -0.5f, 0.5f, 0.0f, -0.5f, 0.0f, 0.75f, 0.25f); opengl_draw_textured_quad(-1.0f, -0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 1.0f); glUniform1iARB( opengl_shader_get_uniform("index"), 2); opengl_draw_textured_quad(-0.5f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 1.0f, 1.0f); glUniform1iARB( opengl_shader_get_uniform("index"), 3); opengl_draw_textured_quad(-0.5f, -1.0f, 0.0f, 0.0f, 0.0f, -0.5f, 1.0f, 1.0f); opengl_shader_set_current(); #endif /*GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_depth_texture); */ // Done! /*GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_effect_texture); opengl_draw_textured_quad(0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_normal_texture); opengl_draw_textured_quad(-1.0f, -0.0f, 0.0f, 0.0f, 0.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_specular_texture); opengl_draw_textured_quad(0.0f, -0.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); */ GL_state.Texture.SetShaderMode(GL_FALSE); // reset state GL_state.DepthTest(depth); GL_state.DepthMask(depth_mask); GL_state.Blend(blend); GL_state.CullFace(cull); opengl_shader_set_current(); Post_in_frame = false; }
void opengl_post_pass_bloom() { // we need the scissor test disabled GLboolean scissor_test = GL_state.ScissorTest(GL_FALSE); // ------ begin bright pass ------ glBindFramebuffer(GL_FRAMEBUFFER, Bloom_framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Bloom_textures[0], 0); // width and height are 1/2 for the bright pass int width = Post_texture_width >> 1; int height = Post_texture_height >> 1; glViewport(0, 0, width, height); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); opengl_shader_set_current( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_BRIGHTPASS, 0) ); Current_shader->program->Uniforms.setUniformi("tex", 0); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_color_texture); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f); // ------ end bright pass ------ // ------ begin blur pass ------ GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Bloom_textures[0]); glGenerateMipmap(GL_TEXTURE_2D); for ( int iteration = 0; iteration < 2; iteration++) { for (int pass = 0; pass < 2; pass++) { GLuint source_tex = Bloom_textures[pass]; GLuint dest_tex = Bloom_textures[1 - pass]; if (pass) { opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_BLUR, SDR_FLAG_BLUR_HORIZONTAL)); } else { opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_BLUR, SDR_FLAG_BLUR_VERTICAL)); } Current_shader->program->Uniforms.setUniformi("tex", 0); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(source_tex); for (int mipmap = 0; mipmap < MAX_MIP_BLUR_LEVELS; ++mipmap) { int bloom_width = width >> mipmap; int bloom_height = height >> mipmap; Current_shader->program->Uniforms.setUniformf("texSize", (pass) ? 1.0f / i2fl(bloom_width) : 1.0f / i2fl(bloom_height)); Current_shader->program->Uniforms.setUniformi("level", mipmap); Current_shader->program->Uniforms.setUniformf("tapSize", 1.0f); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dest_tex, mipmap); glViewport(0, 0, bloom_width, bloom_height); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f); } } } // composite blur to the color texture glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Scene_color_texture, 0); opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_BLOOM_COMP, 0)); Current_shader->program->Uniforms.setUniformi("tex", 0); Current_shader->program->Uniforms.setUniformi("levels", MAX_MIP_BLUR_LEVELS); Current_shader->program->Uniforms.setUniformf("bloom_intensity", Cmdline_bloom_intensity / 100.0f); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Bloom_textures[0]); GL_state.SetAlphaBlendMode( ALPHA_BLEND_ADDITIVE ); glViewport(0, 0, gr_screen.max_w, gr_screen.max_h); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f); GL_state.SetAlphaBlendMode( ALPHA_BLEND_NONE ); // ------ end blur pass -------- // reset viewport, scissor test and exit GL_state.ScissorTest(scissor_test); }