mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-09 04:49:39 -10:00
450 lines
14 KiB
C++
450 lines
14 KiB
C++
#include "lab/renderer/lab_renderer.h"
|
|
#include "lab/labv2_internal.h"
|
|
#include "lab/wmcgui.h"
|
|
#include "graphics/2d.h"
|
|
#include "graphics/light.h"
|
|
#include "starfield/starfield.h"
|
|
#include "starfield/nebula.h"
|
|
#include "nebula/neb.h"
|
|
#include "freespace.h"
|
|
#include "tracing/tracing.h"
|
|
|
|
void LabRenderer::onFrame(float frametime) {
|
|
GR_DEBUG_SCOPE("Lab Frame");
|
|
|
|
gr_reset_clip();
|
|
gr_clear();
|
|
|
|
if (!renderFlags[LabRenderFlag::TimeStopped])
|
|
Missiontime += Frametime;
|
|
|
|
// render our particular thing
|
|
if (getLabManager()->CurrentObject >= 0) {
|
|
int w, h;
|
|
renderModel(frametime);
|
|
|
|
// print out the current pof filename, to help with... something
|
|
if (strlen(getLabManager()->ModelFilename.c_str())) {
|
|
gr_get_string_size(&w, &h, getLabManager()->ModelFilename.c_str());
|
|
gr_set_color_fast(&Color_white);
|
|
gr_string(gr_screen.center_offset_x + gr_screen.center_w - w,
|
|
gr_screen.center_offset_y + gr_screen.center_h - h, getLabManager()->ModelFilename.c_str(), GR_RESIZE_NONE);
|
|
}
|
|
}
|
|
|
|
renderHud(frametime);
|
|
|
|
// Normally, we would call gr_flip here, but because wmcgui conflates rendering and input gathering, this is done at the end of
|
|
// the LabManager::onFrame method
|
|
}
|
|
|
|
void LabRenderer::renderModel(float frametime) {
|
|
GR_DEBUG_SCOPE("Lab Render Model");
|
|
|
|
auto lab_debris_override_save = Motion_debris_enabled;
|
|
auto lab_envmap_override_save = Envmap_override;
|
|
auto lab_emissive_light_save = Cmdline_emissive;
|
|
|
|
light_reset();
|
|
|
|
Cmdline_emissive = renderFlags[LabRenderFlag::ShowEmissiveLighting];
|
|
|
|
object* obj = &Objects[getLabManager()->CurrentObject];
|
|
|
|
obj->pos = getLabManager()->CurrentPosition;
|
|
obj->orient = getLabManager()->CurrentOrientation;
|
|
|
|
Envmap_override = renderFlags[LabRenderFlag::NoEnvMap];
|
|
Glowpoint_override = renderFlags[LabRenderFlag::NoGlowpoints];
|
|
PostProcessing_override = renderFlags[LabRenderFlag::HidePostProcessing];
|
|
|
|
if (obj->type == OBJ_SHIP) {
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Rotators_locked, !renderFlags[LabRenderFlag::RotateSubsystems]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Draw_as_wireframe, renderFlags[LabRenderFlag::ShowWireframe]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_full_detail, renderFlags[LabRenderFlag::ShowFullDetail]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_light, renderFlags[LabRenderFlag::NoLighting] || currentMissionBackground == "None");
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_diffuse, renderFlags[LabRenderFlag::NoDiffuseMap]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_glowmap, renderFlags[LabRenderFlag::NoGlowMap]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_normalmap, renderFlags[LabRenderFlag::NoNormalMap]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_specmap, renderFlags[LabRenderFlag::NoSpecularMap]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_heightmap, renderFlags[LabRenderFlag::NoHeightMap]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_miscmap, renderFlags[LabRenderFlag::NoMiscMap]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_weapons, !renderFlags[LabRenderFlag::ShowWeapons]);
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::Render_without_ambientmap, renderFlags[LabRenderFlag::NoAOMap]);
|
|
|
|
ship_model_update_instance(obj);
|
|
|
|
Ships[obj->instance].team_name = currentTeamColor;
|
|
|
|
if (renderFlags[LabRenderFlag::ShowDamageLightning]) {
|
|
obj->hull_strength = 1.0f;
|
|
}
|
|
else {
|
|
obj->hull_strength = Ship_info[Ships[obj->instance].ship_info_index].max_hull_strength;
|
|
}
|
|
}
|
|
|
|
if (renderFlags[LabRenderFlag::ShowWireframe])
|
|
model_render_set_wireframe_color(&Color_white);
|
|
|
|
if (renderFlags[LabRenderFlag::ShowThrusters] || renderFlags[LabRenderFlag::ShowAfterburners]) {
|
|
obj->phys_info.forward_thrust = 1.0f;
|
|
if (obj->type == OBJ_SHIP) {
|
|
Ships[obj->instance].flags.remove(Ship::Ship_Flags::No_thrusters);
|
|
}
|
|
if (renderFlags[LabRenderFlag::ShowAfterburners]) {
|
|
obj->phys_info.flags |= PF_AFTERBURNER_ON;
|
|
// Keep the AB topped off
|
|
Ships[obj->instance].afterburner_fuel = Ship_info[Ships[obj->instance].ship_info_index].afterburner_fuel_capacity;
|
|
}
|
|
else
|
|
obj->phys_info.flags &= ~PF_AFTERBURNER_ON;
|
|
}
|
|
else {
|
|
obj->phys_info.forward_thrust = 0.0f;
|
|
|
|
if (obj->type == OBJ_SHIP)
|
|
Ships[obj->instance].flags.set(Ship::Ship_Flags::No_thrusters);
|
|
}
|
|
|
|
obj_move_all(frametime);
|
|
if (getLabManager()->CurrentMode == LabMode::Ship)
|
|
process_subobjects(getLabManager()->CurrentObject);
|
|
particle::move_all(frametime);
|
|
particle::ParticleManager::get()->doFrame(frametime);
|
|
shockwave_move_all(frametime);
|
|
|
|
Trail_render_override = true;
|
|
game_render_frame(labCamera->FS_camera);
|
|
Trail_render_override = false;
|
|
|
|
Motion_debris_enabled = lab_debris_override_save;
|
|
Envmap_override = lab_envmap_override_save;
|
|
Cmdline_emissive = lab_emissive_light_save;
|
|
|
|
gr_reset_clip();
|
|
gr_set_color_fast(&HUD_color_debug);
|
|
if (Cmdline_frame_profile) {
|
|
tracing::frame_profile_process_frame();
|
|
gr_string(gr_screen.center_offset_x + 20, gr_screen.center_offset_y + 100 + gr_get_font_height() + 1,
|
|
tracing::get_frame_profile_output().c_str(), GR_RESIZE_NONE);
|
|
}
|
|
}
|
|
|
|
SCP_string get_rot_mode_string(LabRotationMode rotmode)
|
|
{
|
|
switch (rotmode) {
|
|
case LabRotationMode::Both:
|
|
return "Manual rotation mode: Pitch and Yaw";
|
|
case LabRotationMode::Pitch:
|
|
return "Manual rotation mode: Pitch";
|
|
case LabRotationMode::Yaw:
|
|
return "Manual rotation mode: Yaw";
|
|
case LabRotationMode::Roll:
|
|
return "Manual rotation mode: Roll";
|
|
default:
|
|
return "HOW DID THIS HAPPEN? Ask a coder!";
|
|
}
|
|
}
|
|
|
|
SCP_string get_rot_speed_string(float speed_divisor)
|
|
{
|
|
auto exp = std::lroundf(log10f(speed_divisor));
|
|
|
|
switch (exp) {
|
|
case 2:
|
|
return "Fast";
|
|
case 3:
|
|
return "Slow";
|
|
case 4:
|
|
return "Slowest";
|
|
default:
|
|
return "HOW DID THIS HAPPEN? Ask a coder!";
|
|
}
|
|
}
|
|
|
|
void LabRenderer::renderHud(float) {
|
|
GR_DEBUG_SCOPE("Lab Render HUD");
|
|
|
|
// print FPS at bottom left, might be helpful
|
|
extern void game_get_framerate();
|
|
extern float frametotal;
|
|
extern float Framerate;
|
|
|
|
game_get_framerate();
|
|
|
|
gr_set_color_fast(&Color_white);
|
|
|
|
if (frametotal != 0.0f) {
|
|
gr_printf_no_resize(gr_screen.center_offset_x + 2,
|
|
gr_screen.center_offset_y + gr_screen.center_h - gr_get_font_height(),
|
|
"FPS: %3i %s", (int)std::lround(Framerate), labCamera->getOnFrameInfo().c_str());
|
|
}
|
|
else {
|
|
gr_string(gr_screen.center_offset_x + 10, gr_screen.center_offset_y + gr_screen.center_h - gr_get_font_height(),
|
|
"FPS: ?", GR_RESIZE_NONE);
|
|
}
|
|
|
|
//Print FXAA preset
|
|
if ((gr_is_fxaa_mode(Gr_aa_mode) || gr_is_smaa_mode(Gr_aa_mode)) && !PostProcessing_override) {
|
|
const char* aa_mode;
|
|
switch (Gr_aa_mode) {
|
|
case AntiAliasMode::FXAA_Low:
|
|
aa_mode = "FXAA Low";
|
|
break;
|
|
case AntiAliasMode::FXAA_Medium:
|
|
aa_mode = "FXAA Medium";
|
|
break;
|
|
case AntiAliasMode::FXAA_High:
|
|
aa_mode = "FXAA High";
|
|
break;
|
|
case AntiAliasMode::SMAA_Low:
|
|
aa_mode = "SMAA Low";
|
|
break;
|
|
case AntiAliasMode::SMAA_Medium:
|
|
aa_mode = "SMAA Medium";
|
|
break;
|
|
case AntiAliasMode::SMAA_High:
|
|
aa_mode = "SMAA High";
|
|
break;
|
|
case AntiAliasMode::SMAA_Ultra:
|
|
aa_mode = "SMAA Ultra";
|
|
break;
|
|
default:
|
|
aa_mode = "None";
|
|
break;
|
|
}
|
|
|
|
gr_printf_no_resize(gr_screen.center_offset_x + 2, gr_screen.center_offset_y + gr_screen.center_h - (gr_get_font_height() * 2) - 3, "AA Preset: %s", aa_mode);
|
|
}
|
|
|
|
//Print current Team Color setting, if any
|
|
if (currentTeamColor != "<none>") {
|
|
gr_printf_no_resize(gr_screen.center_offset_x + 2,
|
|
gr_screen.center_offset_y + gr_screen.center_h - (gr_get_font_height() * 3) - 3,
|
|
"Use T and Y to cycle through available Team Color settings. Current: %s",
|
|
currentTeamColor.c_str());
|
|
}
|
|
|
|
// Camera usage info
|
|
gr_printf_no_resize(gr_screen.center_offset_x + 2,
|
|
gr_screen.center_offset_y + gr_screen.center_h - (gr_get_font_height() * 4) - 3,
|
|
"%s Use number keys to switch between AA presets. R to cycle model rotation "
|
|
"modes, S to cycle model rotation speeds, V to reset view.", labCamera->getUsageInfo().c_str());
|
|
|
|
// Rotation mode
|
|
SCP_string text = get_rot_mode_string(getLabManager()->RotationMode);
|
|
gr_printf_no_resize(gr_screen.center_offset_x + 2,
|
|
gr_screen.center_offset_y + gr_screen.center_h - (gr_get_font_height() * 5) - 3,
|
|
"%s Rotation speed: %s", get_rot_mode_string(getLabManager()->RotationMode).c_str(),
|
|
get_rot_speed_string(getLabManager()->RotationSpeedDivisor).c_str());
|
|
}
|
|
|
|
void LabRenderer::useBackground(const SCP_string& mission_name) {
|
|
matrix skybox_orientation;
|
|
char skybox_model[MAX_FILENAME_LEN];
|
|
int skybox_flags;
|
|
|
|
int ambient_light_level;
|
|
extern const char* Neb2_filenames[];
|
|
|
|
char envmap_name[MAX_FILENAME_LEN];
|
|
|
|
currentMissionBackground = mission_name;
|
|
|
|
stars_pre_level_init(true);
|
|
vm_set_identity(&skybox_orientation);
|
|
|
|
// (DahBlount) - Remember to load the debris anims
|
|
stars_load_debris(false);
|
|
|
|
if (mission_name != "None") {
|
|
read_file_text((mission_name + ".fs2").c_str(), CF_TYPE_MISSIONS);
|
|
reset_parse();
|
|
|
|
flagset<Mission::Mission_Flags> flags;
|
|
skip_to_start_of_string("+Flags");
|
|
if (optional_string("+Flags:"))
|
|
stuff_flagset(&flags);
|
|
|
|
// Are we using a skybox?
|
|
skip_to_start_of_string_either("$Skybox Model:", "#Background bitmaps");
|
|
|
|
strcpy_s(skybox_model, "");
|
|
if (optional_string("$Skybox Model:")) {
|
|
stuff_string(skybox_model, F_NAME, MAX_FILENAME_LEN);
|
|
|
|
if (optional_string("+Skybox Orientation:")) {
|
|
stuff_matrix(&skybox_orientation);
|
|
}
|
|
|
|
if (optional_string("+Skybox Flags:")) {
|
|
skybox_flags = 0;
|
|
stuff_int(&skybox_flags);
|
|
}
|
|
else {
|
|
skybox_flags = DEFAULT_NMODEL_FLAGS;
|
|
}
|
|
|
|
stars_set_background_model(skybox_model, nullptr, skybox_flags);
|
|
stars_set_background_orientation(&skybox_orientation);
|
|
|
|
skip_to_start_of_string("#Background bitmaps");
|
|
}
|
|
|
|
if (optional_string("#Background bitmaps")) {
|
|
required_string("$Num stars:");
|
|
stuff_int(&Num_stars);
|
|
if (Num_stars >= MAX_STARS)
|
|
Num_stars = MAX_STARS;
|
|
|
|
required_string("$Ambient light level:");
|
|
stuff_int(&ambient_light_level);
|
|
|
|
if (ambient_light_level == 0) {
|
|
ambient_light_level = DEFAULT_AMBIENT_LIGHT_LEVEL;
|
|
}
|
|
|
|
gr_set_ambient_light(ambient_light_level & 0xff, (ambient_light_level >> 8) & 0xff,
|
|
(ambient_light_level >> 16) & 0xff);
|
|
|
|
strcpy_s(Neb2_texture_name, "Eraseme3");
|
|
Neb2_poof_flags = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5));
|
|
if (optional_string("+Neb2:")) {
|
|
stuff_string(Neb2_texture_name, F_NAME, MAX_FILENAME_LEN);
|
|
|
|
required_string("+Neb2Flags:");
|
|
stuff_int(&Neb2_poof_flags);
|
|
|
|
if (flags[Mission::Mission_Flags::Fullneb]) {
|
|
neb2_post_level_init();
|
|
}
|
|
}
|
|
|
|
if (flags[Mission::Mission_Flags::Fullneb]) {
|
|
// no regular nebula stuff
|
|
nebula_close();
|
|
}
|
|
else {
|
|
Nebula_index = -1;
|
|
if (optional_string("+Nebula:")) {
|
|
char str[MAX_FILENAME_LEN];
|
|
int z;
|
|
stuff_string(str, F_NAME, MAX_FILENAME_LEN);
|
|
|
|
// parse the proper nebula type (full or not)
|
|
for (z = 0; z < NUM_NEBULAS; z++) {
|
|
if (flags[Mission::Mission_Flags::Fullneb]) {
|
|
if (!stricmp(str, Neb2_filenames[z])) {
|
|
Nebula_index = z;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (!stricmp(str, Nebula_filenames[z])) {
|
|
Nebula_index = z;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (z == NUM_NEBULAS)
|
|
WarningEx(LOCATION, "Unknown nebula %s!", str);
|
|
|
|
if (optional_string("+Color:")) {
|
|
stuff_string(str, F_NAME, MAX_FILENAME_LEN);
|
|
for (z = 0; z < NUM_NEBULA_COLORS; z++) {
|
|
if (!stricmp(str, Nebula_colors[z])) {
|
|
Mission_palette = z;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (z == NUM_NEBULA_COLORS)
|
|
WarningEx(LOCATION, "Unknown nebula color %s!", str);
|
|
|
|
if (optional_string("+Pitch:")) {
|
|
stuff_int(&Nebula_pitch);
|
|
}
|
|
else {
|
|
Nebula_pitch = 0;
|
|
}
|
|
|
|
if (optional_string("+Bank:")) {
|
|
stuff_int(&Nebula_bank);
|
|
}
|
|
else {
|
|
Nebula_bank = 0;
|
|
}
|
|
|
|
if (optional_string("+Heading:")) {
|
|
stuff_int(&Nebula_heading);
|
|
}
|
|
else {
|
|
Nebula_heading = 0;
|
|
}
|
|
}
|
|
|
|
if (Nebula_index >= 0) {
|
|
nebula_init(Nebula_filenames[Nebula_index], Nebula_pitch, Nebula_bank, Nebula_heading);
|
|
}
|
|
else {
|
|
nebula_close();
|
|
}
|
|
}
|
|
|
|
stars_load_debris(flags[Mission::Mission_Flags::Fullneb]);
|
|
|
|
|
|
extern void parse_one_background(background_t * background);
|
|
while (optional_string("$Bitmap List:") || check_for_string("$Sun:") || check_for_string("$Starbitmap:")) {
|
|
Backgrounds.emplace_back();
|
|
parse_one_background(&Backgrounds.back());
|
|
}
|
|
|
|
stars_load_first_valid_background();
|
|
|
|
if (optional_string("$Environment Map:")) {
|
|
stuff_string(envmap_name, F_NAME, MAX_FILENAME_LEN);
|
|
}
|
|
|
|
const int size = 512;
|
|
int gen_flags = (BMP_FLAG_RENDER_TARGET_STATIC | BMP_FLAG_CUBEMAP | BMP_FLAG_RENDER_TARGET_MIPMAP);
|
|
|
|
if (!Cmdline_env) {
|
|
return;
|
|
}
|
|
|
|
if (gr_screen.envmap_render_target >= 0) {
|
|
if (!bm_release(gr_screen.envmap_render_target, 1)) {
|
|
Warning(LOCATION, "Unable to release environment map render target.");
|
|
}
|
|
|
|
gr_screen.envmap_render_target = -1;
|
|
}
|
|
|
|
if (strlen(envmap_name)) {
|
|
// Load the mission map so we can use it later
|
|
ENVMAP = bm_load(The_mission.envmap_name);
|
|
return;
|
|
}
|
|
|
|
gr_screen.envmap_render_target = bm_make_render_target(size, size, gen_flags);
|
|
}
|
|
}
|
|
else {
|
|
// (DahBlount) - This spot should be used to disable rendering features that only apply to missions.
|
|
Motion_debris_override = true;
|
|
Num_stars = 0;
|
|
}
|
|
}
|
|
|
|
LabCamera* LabRenderer::getCurrentCamera() {
|
|
return labCamera;
|
|
}
|
|
|
|
void LabRenderer::setCurrentCamera(LabCamera* newcam) {
|
|
delete labCamera;
|
|
labCamera = newcam;
|
|
} |