void opengl_draw_textured_quad(GLfloat x1, GLfloat y1, GLfloat u1, GLfloat v1, GLfloat x2, GLfloat y2, GLfloat u2, GLfloat v2) { GR_DEBUG_SCOPE("Draw textured quad"); GLfloat glVertices[4][4] = { { x1, y1, u1, v1 }, { x1, y2, u1, v2 }, { x2, y1, u2, v1 }, { x2, y2, u2, v2 } }; vertex_layout vert_def; vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(GLfloat) * 4, 0); vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(GLfloat) * 4, sizeof(GLfloat) * 2); opengl_render_primitives_immediate(PRIM_TYPE_TRISTRIP, &vert_def, 4, glVertices, sizeof(GLfloat) * 4 * 4); }
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); }
static bool load_cached_shader_binary(opengl::ShaderProgram* program, const SCP_string& hash) { if (!do_shader_caching()) { return false; } auto base_filename = SCP_string("ogl_shader-") + hash; auto metadata = base_filename + ".json"; auto binary = base_filename + ".bin"; auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!metadata_fp) { nprintf(("ShaderCache", "Metadata file does not exist.\n")); return false; } auto size = cfilelength(metadata_fp); SCP_string metadata_content; metadata_content.resize((size_t) size); cfread(&metadata_content[0], 1, size, metadata_fp); cfclose(metadata_fp); auto metadata_root = json_loads(metadata_content.c_str(), 0, nullptr); if (!metadata_root) { mprintf(("Loading of cache metadata failed! Falling back to GLSL shader...\n")); return false; } json_int_t format; if (json_unpack(metadata_root, "{sI}", "format", &format) != 0) { mprintf(("Failed to unpack values from metadata JSON! Falling back to GLSL shader...\n")); return false; } auto binary_format = (GLenum) format; json_decref(metadata_root); bool supported = false; for (auto supported_fmt : GL_binary_formats) { if ((GLenum)supported_fmt == binary_format) { supported = true; break; } } if (!supported) { // This can happen in case an implementation stops supporting a particular binary format nprintf(("ShaderCache", "Unsupported binary format %d encountered in shader cache.\n", binary_format)); return false; } auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!binary_fp) { nprintf(("ShaderCache", "Binary file does not exist.\n")); return false; } GR_DEBUG_SCOPE("Loading cached shader"); SCP_vector<uint8_t> buffer; int length = cfilelength(binary_fp); buffer.resize((size_t) length); cfread(&buffer[0], 1, length, binary_fp); cfclose(binary_fp); // Load the data! glProgramBinary(program->getShaderHandle(), binary_format, buffer.data(), (GLsizei) buffer.size()); // Check the status... GLint status; glGetProgramiv(program->getShaderHandle(), GL_LINK_STATUS, &status); return status == GL_TRUE; }
void credits_do_frame(float frametime) { GR_DEBUG_SCOPE("Credits do frame"); int i, k, next, percent, bm1, bm2; int bx1, by1, bw1, bh1; int bx2, by2, bw2, bh2; // Use this id to trigger the start of music playing on the credits screen if ( timestamp_elapsed(Credits_music_begin_timestamp) ) { Credits_music_begin_timestamp = 0; credits_start_music(); } k = Ui_window.process(); switch (k) { case KEY_ESC: gameseq_post_event(GS_EVENT_MAIN_MENU); key_flush(); break; case KEY_CTRLED | KEY_UP: case KEY_SHIFTED | KEY_TAB: if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) { credits_screen_button_pressed(CUTSCENES_BUTTON); break; } // else, react like tab key. case KEY_CTRLED | KEY_DOWN: case KEY_TAB: credits_screen_button_pressed(TECH_DATABASE_BUTTON); break; default: break; } // end switch for (i=0; i<NUM_BUTTONS; i++){ if (Buttons[i][gr_screen.res].button.pressed()){ if (credits_screen_button_pressed(i)){ return; } } } gr_reset_clip(); GR_MAYBE_CLEAR_RES(Background_bitmap); if (Background_bitmap >= 0) { gr_set_bitmap(Background_bitmap); gr_bitmap(0, 0, GR_RESIZE_MENU); } percent = (int) (100.0f - (Credits_artwork_display_time - Credits_counter) * 100.0f / Credits_artwork_fade_time); if (percent < 0){ percent = 0; } next = Credits_artwork_index + 1; if (next >= Credits_num_images){ next = 0; } if (Credits_bmps[Credits_artwork_index] < 0) { char buf[40]; if (gr_screen.res == GR_1024) { sprintf(buf, NOX("2_CrIm%.2d"), Credits_artwork_index); } else { sprintf(buf, NOX("CrIm%.2d"), Credits_artwork_index); } Credits_bmps[Credits_artwork_index] = bm_load(buf); } if (Credits_bmps[next] < 0) { char buf[40]; if (gr_screen.res == GR_1024) { sprintf(buf, NOX("2_CrIm%.2d"), next); } else { sprintf(buf, NOX("CrIm%.2d"), next); } Credits_bmps[next] = bm_load(buf); } bm1 = Credits_bmps[Credits_artwork_index]; bm2 = Credits_bmps[next]; if((bm1 != -1) && (bm2 != -1)){ GR_DEBUG_SCOPE("Render credits bitmap"); Assert(percent >= 0 && percent <= 100); // get width and height bm_get_info(bm1, &bw1, &bh1, NULL, NULL, NULL); bm_get_info(bm2, &bw2, &bh2, NULL, NULL, NULL); // determine where to draw the coords bx1 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw1)/2); by1 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh1)/2); bx2 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw2)/2); by2 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh2)/2); auto alpha = (float)percent / 100.0f; gr_set_bitmap(bm1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f - alpha); gr_bitmap(bx1, by1, GR_RESIZE_MENU); gr_set_bitmap(bm2, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha); gr_bitmap(bx2, by2, GR_RESIZE_MENU); } Ui_window.draw(); for (i=TECH_DATABASE_BUTTON; i<=CREDITS_BUTTON; i++){ if (Buttons[i][gr_screen.res].button.button_down()){ break; } } if (i > CREDITS_BUTTON){ Buttons[CREDITS_BUTTON][gr_screen.res].button.draw_forced(2); } gr_set_clip(Credits_text_coords[gr_screen.res][CREDITS_X_COORD], Credits_text_coords[gr_screen.res][CREDITS_Y_COORD], Credits_text_coords[gr_screen.res][CREDITS_W_COORD], Credits_text_coords[gr_screen.res][CREDITS_H_COORD], GR_RESIZE_MENU); font::set_font(font::FONT1); gr_set_color_fast(&Color_normal); int y_offset = 0; for (SCP_vector<SCP_string>::iterator iter = Credit_text_parts.begin(); iter != Credit_text_parts.end(); ++iter) { size_t currentPos = 0; size_t lineEnd; do { int height; int width; lineEnd = iter->find('\n', currentPos); auto length = lineEnd - currentPos; if (lineEnd == SCP_string::npos) { length = std::numeric_limits<size_t>::max(); } gr_get_string_size(&width, &height, iter->c_str() + currentPos, static_cast<int>(length)); // Check if the text part is actually visible if (Credit_position + y_offset + height > 0.0f) { float x = static_cast<float>((gr_screen.clip_width_unscaled - width) / 2); gr_string(x, Credit_position + y_offset, iter->c_str() + currentPos, GR_RESIZE_MENU, static_cast<int>(length)); } y_offset += height; currentPos = lineEnd + 1; } while (lineEnd < iter->length() && lineEnd != SCP_string::npos); } int temp_time; temp_time = timer_get_milliseconds(); Credits_frametime = temp_time - Credits_last_time; Credits_last_time = temp_time; timestamp_inc(i2f(Credits_frametime) / TIMESTAMP_FREQUENCY); float fl_frametime = i2fl(Credits_frametime) / 1000.f; if (keyd_pressed[KEY_LSHIFT]) { Credit_position -= fl_frametime * Credits_scroll_rate * 4.0f; } else { Credit_position -= fl_frametime * Credits_scroll_rate; } if (Credit_position < Credit_stop_pos){ Credit_position = Credit_start_pos; } Credits_counter += fl_frametime; while (Credits_counter >= Credits_artwork_display_time) { Credits_counter -= Credits_artwork_display_time; Credits_artwork_index = next; } gr_flip(); }
static bool load_cached_shader_binary(opengl::ShaderProgram* program, SCP_string hash) { if (!do_shader_caching()) { return false; } auto base_filename = SCP_string("ogl_shader-") + hash; auto metadata = base_filename + ".json"; auto binary = base_filename + ".bin"; auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE); if (!metadata_fp) { nprintf(("ShaderCache", "Metadata file does not exist.\n")); return false; } auto size = cfilelength(metadata_fp); SCP_string metadata_content; metadata_content.resize((size_t) size); cfread(&metadata_content[0], 1, size, metadata_fp); cfclose(metadata_fp); auto metadata_root = json_loads(metadata_content.c_str(), 0, nullptr); if (!metadata_root) { mprintf(("Loading of cache metadata failed! Falling back to GLSL shader...\n")); return false; } json_int_t format; if (json_unpack(metadata_root, "{sI}", "format", &format) != 0) { mprintf(("Failed to unpack values from metadata JSON! Falling back to GLSL shader...\n")); return false; } auto binary_format = (GLenum) format; json_decref(metadata_root); auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE); if (!binary_fp) { nprintf(("ShaderCache", "Binary file does not exist.\n")); return false; } GR_DEBUG_SCOPE("Loading cached shader"); SCP_vector<uint8_t> buffer; int length = cfilelength(binary_fp); buffer.resize((size_t) length); cfread(&buffer[0], 1, length, binary_fp); cfclose(binary_fp); // Load the data! glProgramBinary(program->getShaderHandle(), binary_format, buffer.data(), (GLsizei) buffer.size()); // Check the status... GLint status; glGetProgramiv(program->getShaderHandle(), GL_LINK_STATUS, &status); return status == GL_TRUE; }
void gr_opengl_update_distortion() { if (Distortion_framebuffer == 0) { // distortion is disabled return; } GR_DEBUG_SCOPE("Update distortion"); TRACE_SCOPE(tracing::UpdateDistortion); 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); opengl_shader_set_passthrough(true); GL_state.PushFramebufferState(); GL_state.BindFrameBuffer(Distortion_framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Distortion_texture[!Distortion_switch], 0); glDrawBuffer(GL_COLOR_ATTACHMENT0); glViewport(0,0,32,32); GL_state.Texture.Enable(0, GL_TEXTURE_2D, Distortion_texture[Distortion_switch]); glClearColor(0.5f, 0.5f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); vertex vertices[4]; vertices[0].texture_position.u = 0.0f; vertices[0].texture_position.v = 0.0f; vertices[1].texture_position.u = 0.96875f; vertices[1].texture_position.v = 0.0f; vertices[2].texture_position.u = 0.0f; vertices[2].texture_position.v = 1.0f; vertices[3].texture_position.u = 0.96875f; vertices[3].texture_position.v = 1.0f; vertices[0].screen.xyw.x = 0.03f*(float)gr_screen.max_w; vertices[0].screen.xyw.y = (float)gr_screen.max_h; vertices[1].screen.xyw.x = (float)gr_screen.max_w; vertices[1].screen.xyw.y = (float)gr_screen.max_h; vertices[2].screen.xyw.x = 0.03f*(float)gr_screen.max_w; vertices[2].screen.xyw.y = 0.0f; vertices[3].screen.xyw.x = (float)gr_screen.max_w; vertices[3].screen.xyw.y = 0.0f; vertex_layout vert_def; vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex), offsetof(vertex, screen)); vert_def.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex), offsetof(vertex, texture_position)); opengl_render_primitives_immediate(PRIM_TYPE_TRISTRIP, &vert_def, 4, vertices, sizeof(vertex) * 4); opengl_shader_set_passthrough(false); vertex distortion_verts[33]; for(int i = 0; i < 33; i++) { distortion_verts[i].r = (ubyte)rand() % 256; distortion_verts[i].g = (ubyte)rand() % 256; distortion_verts[i].b = 255; distortion_verts[i].a = 255; distortion_verts[i].screen.xyw.x = 1.f; distortion_verts[i].screen.xyw.y = (float)gr_screen.max_h*0.03125f*i; } vert_def = vertex_layout(); vert_def.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex), offsetof(vertex, screen)); vert_def.add_vertex_component(vertex_format_data::COLOR4, sizeof(vertex), offsetof(vertex, r)); opengl_render_primitives_immediate(PRIM_TYPE_POINTS, &vert_def, 33, distortion_verts, 33 * sizeof(vertex)); Distortion_switch = !Distortion_switch; // reset state GL_state.PopFramebufferState(); glViewport(0,0,gr_screen.max_w,gr_screen.max_h); GL_state.DepthTest(depth); GL_state.DepthMask(depth_mask); GL_state.Blend(blend); GL_state.CullFace(cull); }
void gr_opengl_scene_texture_end() { if ( !Scene_framebuffer_in_frame ) { return; } GR_DEBUG_SCOPE("End scene texture"); TRACE_SCOPE(tracing::SceneTextureEnd); time_buffer+=flFrametime; if(time_buffer>0.03f) { gr_opengl_update_distortion(); time_buffer = 0.0f; } if ( Gr_post_processing_enabled && !PostProcessing_override ) { gr_post_process_end(); } else { GR_DEBUG_SCOPE("Draw scene texture"); TRACE_SCOPE(tracing::DrawSceneTexture); 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.PopFramebufferState(); GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_color_texture); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); opengl_shader_set_passthrough(true); GL_state.Array.BindArrayBuffer(0); if (GL_rendering_to_texture) { opengl_draw_textured_quad(0.0f, 0.0f, 0.0f, 0.0f, (float)gr_screen.max_w, (float)gr_screen.max_h, Scene_texture_u_scale, Scene_texture_v_scale); } else { opengl_draw_textured_quad(0.0f, 0.0f, 0.0f, Scene_texture_v_scale, (float)gr_screen.max_w, (float)gr_screen.max_h, Scene_texture_u_scale, 0.0f); } // reset state GL_state.DepthTest(depth); GL_state.DepthMask(depth_mask); GL_state.Blend(blend); GL_state.CullFace(cull); } // Reset the UV scale values Scene_texture_u_scale = 1.0f; Scene_texture_v_scale = 1.0f; Scene_framebuffer_in_frame = false; High_dynamic_range = false; }
void HudGaugeShield::showShields(object *objp, int mode) { // static int fod_model = -1; float max_shield; int hud_color_index, range; int sx, sy, i; ship *sp; ship_info *sip; hud_frames *sgp=NULL; if ( objp->type != OBJ_SHIP ) return; // Goober5000 - don't show if primitive sensors if ( Ships[Player_obj->instance].flags[Ship::Ship_Flags::Primitive_sensors] ) return; sp = &Ships[objp->instance]; sip = &Ship_info[sp->ship_info_index]; // bool digitus_improbus = (fod_model != -2 && strstr(sp->ship_name, "Sathanas") != NULL); if ( sip->shield_icon_index == 255 && !(sip->flags[Ship::Info_Flags::Generate_hud_icon]) /*&& !digitus_improbus*/) { return; } setGaugeColor(); // load in shield frames if not already loaded if (sip->shield_icon_index != 255) { sgp = &Shield_gauges.at(sip->shield_icon_index); if ( (sgp->first_frame == -1) && (sip->shield_icon_index < Hud_shield_filenames.size()) ) { sgp->first_frame = bm_load_animation(Hud_shield_filenames.at(sip->shield_icon_index).c_str(), &sgp->num_frames); if (sgp->first_frame == -1) { if (!shield_ani_warning_displayed_already) { shield_ani_warning_displayed_already = true; Warning(LOCATION, "Could not load in the HUD shield ani: %s\n", Hud_shield_filenames.at(sip->shield_icon_index).c_str()); } return; } } } sx = position[0]; sy = position[1]; sx += fl2i(HUD_offset_x); sy += fl2i(HUD_offset_y); // draw the ship first maybeFlashShield(SHIELD_HIT_PLAYER, Shield_hit_data[SHIELD_HIT_PLAYER].hull_hit_index); if(sip->shield_icon_index != 255) { renderBitmap(sgp->first_frame, sx, sy); } else { GR_DEBUG_SCOPE("Render generated shield icon"); bool g3_yourself = !g3_in_frame(); angles rot_angles = {-1.570796327f,0.0f,0.0f}; matrix object_orient; vm_angles_2_matrix(&object_orient, &rot_angles); const int CLIP_WIDTH = 112; const int CLIP_HEIGHT = 93; gr_screen.clip_width = CLIP_WIDTH; gr_screen.clip_height = CLIP_HEIGHT; //Fire it up if(g3_yourself) g3_start_frame(1); hud_save_restore_camera_data(1); setClip(sx, sy, CLIP_WIDTH, CLIP_HEIGHT); //if(!digitus_improbus) g3_set_view_matrix( &sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 2.5f); /*else { vec3d finger_vec = {0.0f, 0.0f, 176.0f}; g3_set_view_matrix( &finger_vec, &vmd_identity_matrix, 1.0f); }*/ gr_set_proj_matrix(0.5f*Proj_fov, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance); gr_set_view_matrix(&Eye_position, &Eye_matrix); //We're ready to show stuff //if(!digitus_improbus) { model_render_params render_info; render_info.set_flags(MR_NO_LIGHTING | MR_AUTOCENTER | MR_NO_FOGGING); render_info.set_replacement_textures(sp->ship_replacement_textures); render_info.set_detail_level_lock(1); render_info.set_object_number(OBJ_INDEX(objp)); model_render_immediate( &render_info, sip->model_num, &object_orient, &vmd_zero_vector ); } /*else { if(fod_model == -1) { fod_model = model_load(NOX("FoD.pof"), 0, NULL); if(fod_model == -1) { fod_model = -2; return; } } model_render(fod_model, &object_orient, &vmd_zero_vector, MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER | MR_NO_FOGGING, -1, -1); }*/ //We're done gr_end_view_matrix(); gr_end_proj_matrix(); if(g3_yourself) g3_end_frame(); hud_save_restore_camera_data(0); resetClip(); } if(!sip->max_shield_strength) return; // draw the quadrants // // Draw shield quadrants at one of NUM_SHIELD_LEVELS max_shield = shield_get_max_quad(objp); coord2d shield_icon_coords[6]; for ( i = 0; i < objp->n_quadrants; i++ ) { if ( objp->flags[Object::Object_Flags::No_shields] ) { break; } if ( !(sip->flags[Ship::Info_Flags::Model_point_shields]) ) { if ( objp->shield_quadrant[Quadrant_xlate[i]] < 0.1f ) continue; } else { if ( objp->shield_quadrant[i] < 0.1f ) continue; } GR_DEBUG_SCOPE("Render shield quadrant"); range = MAX(HUD_COLOR_ALPHA_MAX, HUD_color_alpha + objp->n_quadrants); if ( !(sip->flags[Ship::Info_Flags::Model_point_shields]) ) hud_color_index = fl2i( (objp->shield_quadrant[Quadrant_xlate[i]] / max_shield) * range); else hud_color_index = fl2i( (objp->shield_quadrant[i] / max_shield) * range); Assert(hud_color_index >= 0 && hud_color_index <= range); if ( hud_color_index < 0 ) { hud_color_index = 0; } if ( hud_color_index >= HUD_NUM_COLOR_LEVELS ) { hud_color_index = HUD_NUM_COLOR_LEVELS - 1; } int flash=0; flash = maybeFlashShield(mode, i); if ( !flash ) { // gr_set_color_fast(&HUD_color_defaults[hud_color_index]); setGaugeColor(hud_color_index); if(sip->shield_icon_index != 255) { int framenum = sgp->first_frame+i+1; if (framenum < sgp->first_frame+sgp->num_frames) renderBitmap(framenum, sx, sy); } else { //Ugh, draw four shield quadrants static const int TRI_EDGE = 6; static const int BAR_LENGTH = 112; static const int BAR_HEIGHT = 63; static const int BAR_WIDTH = 6; static const int SHIELD_OFFSET = BAR_WIDTH + TRI_EDGE + 3; switch(i) { //Top case 0: shield_icon_coords[0].x = sx; shield_icon_coords[0].y = sy+BAR_WIDTH+TRI_EDGE; shield_icon_coords[1].x = sx; shield_icon_coords[1].y = sy; shield_icon_coords[2].x = sx+TRI_EDGE; shield_icon_coords[2].y = sy+BAR_WIDTH; shield_icon_coords[3].x = sx+BAR_LENGTH; shield_icon_coords[3].y = sy; shield_icon_coords[4].x = sx+BAR_LENGTH-TRI_EDGE; shield_icon_coords[4].y = sy+BAR_WIDTH; shield_icon_coords[5].x = sx+BAR_LENGTH; shield_icon_coords[5].y = sy+BAR_WIDTH+TRI_EDGE; renderShieldIcon(shield_icon_coords); break; //Left case 3: sy += SHIELD_OFFSET; shield_icon_coords[0].x = sx+BAR_WIDTH+TRI_EDGE; shield_icon_coords[0].y = sy+BAR_HEIGHT; shield_icon_coords[1].x = sx; shield_icon_coords[1].y = sy+BAR_HEIGHT; shield_icon_coords[2].x = sx+BAR_WIDTH; shield_icon_coords[2].y = sy+BAR_HEIGHT-TRI_EDGE; shield_icon_coords[3].x = sx; shield_icon_coords[3].y = sy; shield_icon_coords[4].x = sx+BAR_WIDTH; shield_icon_coords[4].y = sy+TRI_EDGE; shield_icon_coords[5].x = sx+BAR_WIDTH+TRI_EDGE; shield_icon_coords[5].y = sy; renderShieldIcon(shield_icon_coords); sy -= SHIELD_OFFSET + BAR_WIDTH + TRI_EDGE; break; //Right case 1: sx += BAR_LENGTH; sy += SHIELD_OFFSET; shield_icon_coords[0].x = sx-BAR_WIDTH-TRI_EDGE; shield_icon_coords[0].y = sy; shield_icon_coords[1].x = sx; shield_icon_coords[1].y = sy; shield_icon_coords[2].x = sx-BAR_WIDTH; shield_icon_coords[2].y = sy+TRI_EDGE; shield_icon_coords[3].x = sx; shield_icon_coords[3].y = sy+BAR_HEIGHT; shield_icon_coords[4].x = sx-BAR_WIDTH; shield_icon_coords[4].y = sy+BAR_HEIGHT-TRI_EDGE; shield_icon_coords[5].x = sx-BAR_WIDTH-TRI_EDGE; shield_icon_coords[5].y = sy+BAR_HEIGHT; renderShieldIcon(shield_icon_coords); sx -= BAR_LENGTH; sy -= SHIELD_OFFSET; break; //Bottom case 2: sy += BAR_HEIGHT + SHIELD_OFFSET*2 - BAR_WIDTH - TRI_EDGE; shield_icon_coords[0].x = sx+BAR_LENGTH; shield_icon_coords[0].y = sy; shield_icon_coords[1].x = sx+BAR_LENGTH; shield_icon_coords[1].y = sy+BAR_WIDTH+TRI_EDGE; shield_icon_coords[2].x = sx+BAR_LENGTH-TRI_EDGE; shield_icon_coords[2].y = sy+TRI_EDGE; shield_icon_coords[3].x = sx; shield_icon_coords[3].y = sy+BAR_WIDTH+TRI_EDGE; shield_icon_coords[4].x = sx+TRI_EDGE; shield_icon_coords[4].y = sy+TRI_EDGE; shield_icon_coords[5].x = sx; shield_icon_coords[5].y = sy; renderShieldIcon(shield_icon_coords); sy -= BAR_HEIGHT + SHIELD_OFFSET*2 - BAR_WIDTH - TRI_EDGE; break; //Whoops? default: nprintf(("HUD", "Invalid shield quadrant %d specified!\n", i)); break; } } } } // hud_set_default_color(); }