Minor - Adds target FPS control to engine settings - V14.5.0

Adds functionality to control the target FPS of the engine via the ImGui settings panel.

This includes:
- Adding target FPS variables and accessors in the application class.
- Adding a set_target_fps function to the fps_limiter class.
- Updating the ImGui engine settings panel to include a target FPS setting.
- Modifying the main loop to make use of the fps limiter and the engine target FPS.
This commit is contained in:
2025-10-01 16:58:37 +02:00
parent 0e41fb0ec9
commit 389cde97c2
8 changed files with 88 additions and 60 deletions

View File

@@ -16,7 +16,7 @@ DockId=0x00000006,0
[Window][render Stats]
Pos=0,630
Size=1350,231
Size=1265,231
Collapsed=0
DockId=0x00000009,0

View File

@@ -483,6 +483,17 @@ public:
*/
float get_screen_near() const { return screen_near; }
/**
* Get the target fps for the application.
* @return The target fps as an integer.
*/
int get_target_fps() const { return target_fps_; };
/**
* Set the target fps for the application.
* @param target_fps The new target fps as an integer.
*/
void set_target_fps(int target_fps) { target_fps_ = target_fps; };
private:
/**
@@ -690,6 +701,7 @@ private :
ID3D11ShaderResourceView* back_buffer_srv_;
stats* stats_;
int target_fps_ = 60;
// ------------------------------------------------- //
// ------------------- Culling --------------------- //

View File

@@ -3,11 +3,9 @@
class fps_limiter {
public:
/**
* Builder for fps_limiter class
* This class is used to limit the execution rate of a loop based on a target frames per second (FPS).
* @param target_fps Target frames per second for the limiter. The default is 60.0f FPS.
* Constructor for fps_limiter class
* @param target_fps Target frames per second for the limiter. Default is 60.0f FPS.
*/
explicit fps_limiter(const float target_fps = 60.0f)
: min_delta_(1.0f / target_fps), last_time_(std::chrono::high_resolution_clock::now()) {}
@@ -25,7 +23,17 @@ public:
return false;
}
/**
* Dynamically set the target FPS limit.
* @param target_fps New target frames per second.
*/
void set_target_fps(float target_fps) {
if (target_fps > 0.0f) {
min_delta_ = 1.0f / target_fps;
}
}
private:
float min_delta_;
std::chrono::high_resolution_clock::time_point last_time_;
float min_delta_; // Minimum time in seconds between frames
std::chrono::high_resolution_clock::time_point last_time_; // Time point of last allowed execution
};

View File

@@ -66,7 +66,6 @@ private:
std::mutex render_mutex_;
std::unique_ptr<fps_limiter> fps_limiter_ = std::make_unique<fps_limiter>(60);
int target_fps_ = 60;
};

View File

@@ -848,83 +848,63 @@ void imguiManager::WidgetEngineSettingsWindow()
{
ImGui::Begin("Engine Settings", &showEngineSettingsWindow);
// Variables temporaires pour les settings
static bool temp_v_sync = app_->get_vsync();
static int temp_target_fps = app_->get_target_fps();
static float temp_screen_depth = app_->get_screen_depth();
static float temp_screen_near = app_->get_screen_near();
static float temp_frustum_tolerance = app_->get_frustum_tolerance();
static int temp_physics_tick_rate = app_->get_physics_tick_rate();
static float temp_gravity_values[3] = {
XMVectorGetX(app_->get_physics()->GetGravity()),
XMVectorGetY(app_->get_physics()->GetGravity()),
XMVectorGetZ(app_->get_physics()->GetGravity())
};
if (ImGui::BeginTabBar("Engine Settings"))
{
if (ImGui::BeginTabItem("General"))
{
bool v_sync = app_->get_vsync();
if (ImGui::Checkbox("Vsync", &v_sync))
{
app_->set_vsync(v_sync);
}
ImGui::Checkbox("Vsync", &temp_v_sync);
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Enable or disable Vsync");
}
ImGui::InputInt("Target FPS", &temp_target_fps);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Set the target FPS for the engine");
float screen_depth = app_->get_screen_depth();
float screen_near = app_->get_screen_near();
// Drag float input for screen depth and near with min and max values and update the app values on change
if (ImGui::DragFloat("Screen Depth", &screen_depth, 1.f, 0.1f, 10000.0f))
{
app_->update_screen_depth(screen_depth);
}
ImGui::DragFloat("Screen Depth", &temp_screen_depth, 1.f, 0.1f, 10000.0f);
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Set the screen depth");
}
if (ImGui::DragFloat("Screen Near", &screen_near, 1.f, 0.1f, 10000.0f))
{
app_->update_screen_near(screen_near);
}
ImGui::DragFloat("Screen Near", &temp_screen_near, 1.f, 0.1f, 10000.0f);
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Set the screen near");
}
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Culling Settings"))
{
float frustumTolerance = app_->get_frustum_tolerance();
if (ImGui::DragFloat("Frustum Tolerance", &frustumTolerance, 0.1f, 0.0f, 100.0f))
{
app_->set_frustum_tolerance(frustumTolerance);
}
ImGui::DragFloat("Frustum Tolerance", &temp_frustum_tolerance, 0.1f, 0.0f, 100.0f);
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Set the frustum tolerance for culling");
}
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Physics Settings"))
{
int physics_tick_rate = app_->get_physics_tick_rate();
XMVECTOR gravity = app_->get_physics()->GetGravity();
float gravity_values[3] = { XMVectorGetX(gravity), XMVectorGetY(gravity), XMVectorGetZ(gravity) };
if (ImGui::InputInt("Physics Tick Rate", &physics_tick_rate))
{
app_->set_physics_tick_rate(physics_tick_rate);
}
ImGui::InputInt("Physics Tick Rate", &temp_physics_tick_rate);
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Set the physics tick rate (Fixed Update Interval)");
}
if (ImGui::DragFloat3("Gravity", gravity_values))
{
app_->get_physics()->SetGravity(XMVectorSet(gravity_values[0], gravity_values[1], gravity_values[2], 0.0f));
}
ImGui::DragFloat3("Gravity", temp_gravity_values);
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Set the gravity vector for the physics engine");
}
ImGui::EndTabItem();
}
@@ -979,6 +959,30 @@ void imguiManager::WidgetEngineSettingsWindow()
ImGui::EndTabBar();
}
if (ImGui::Button("Apply Settings"))
{
app_->set_vsync(temp_v_sync);
app_->set_target_fps(temp_target_fps);
app_->update_screen_depth(temp_screen_depth);
app_->update_screen_near(temp_screen_near);
app_->set_frustum_tolerance(temp_frustum_tolerance);
app_->set_physics_tick_rate(temp_physics_tick_rate);
app_->get_physics()->SetGravity(XMVectorSet(temp_gravity_values[0], temp_gravity_values[1], temp_gravity_values[2], 0.0f));
}
ImGui::SameLine();
if (ImGui::Button("Reset Settings"))
{
temp_v_sync = app_->get_vsync();
temp_target_fps = app_->get_target_fps();
temp_screen_depth = app_->get_screen_depth();
temp_screen_near = app_->get_screen_near();
temp_frustum_tolerance = app_->get_frustum_tolerance();
temp_physics_tick_rate = app_->get_physics_tick_rate();
temp_gravity_values[0] = XMVectorGetX(app_->get_physics()->GetGravity());
temp_gravity_values[1] = XMVectorGetY(app_->get_physics()->GetGravity());
temp_gravity_values[2] = XMVectorGetZ(app_->get_physics()->GetGravity());
}
ImGui::End();
}

View File

@@ -136,12 +136,17 @@ void system_class::run()
else
{
// Otherwise do the frame processing.
result = frame();
if (!result)
if (fps_limiter_->should_run())
{
Logger::Get().Log("Failed to process frame", __FILE__, __LINE__, Logger::LogLevel::Error);
done = true;
result = frame();
if (!result)
{
Logger::Get().Log("Failed to process frame", __FILE__, __LINE__, Logger::LogLevel::Error);
done = true;
}
fps_limiter_->set_target_fps(application_->get_target_fps());
}
}
}

BIN
x64/Debug/config.txt (Stored with Git LFS)

Binary file not shown.

BIN
x64/Release/config.txt (Stored with Git LFS)

Binary file not shown.