mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
feat: add graphics quality presets system
Implement quick-access quality presets (Low, Medium, High, Ultra) that adjust multiple graphics settings at once for better user experience. Each preset configures: - Shadow rendering and distance - Anti-aliasing (MSAA) level - Normal mapping and parallax mapping - Ground clutter density The system automatically detects when settings deviate from a preset and marks them as "Custom". Presets are persisted to settings.cfg for consistency across sessions. Users can quickly switch between performance and quality modes or tweak individual settings as needed.
This commit is contained in:
parent
6a8939d420
commit
6f7c57d975
2 changed files with 211 additions and 0 deletions
|
|
@ -143,6 +143,17 @@ private:
|
||||||
bool pendingAMDFramegen = false;
|
bool pendingAMDFramegen = false;
|
||||||
bool fsrSettingsApplied_ = false;
|
bool fsrSettingsApplied_ = false;
|
||||||
|
|
||||||
|
// Graphics quality presets
|
||||||
|
enum class GraphicsPreset : int {
|
||||||
|
CUSTOM = 0,
|
||||||
|
LOW = 1,
|
||||||
|
MEDIUM = 2,
|
||||||
|
HIGH = 3,
|
||||||
|
ULTRA = 4
|
||||||
|
};
|
||||||
|
GraphicsPreset currentGraphicsPreset = GraphicsPreset::CUSTOM;
|
||||||
|
GraphicsPreset pendingGraphicsPreset = GraphicsPreset::CUSTOM;
|
||||||
|
|
||||||
// UI element transparency (0.0 = fully transparent, 1.0 = fully opaque)
|
// UI element transparency (0.0 = fully transparent, 1.0 = fully opaque)
|
||||||
float uiOpacity_ = 0.65f;
|
float uiOpacity_ = 0.65f;
|
||||||
bool minimapRotate_ = false;
|
bool minimapRotate_ = false;
|
||||||
|
|
@ -252,6 +263,8 @@ private:
|
||||||
void renderTalentWipeConfirmDialog(game::GameHandler& gameHandler);
|
void renderTalentWipeConfirmDialog(game::GameHandler& gameHandler);
|
||||||
void renderEscapeMenu();
|
void renderEscapeMenu();
|
||||||
void renderSettingsWindow();
|
void renderSettingsWindow();
|
||||||
|
void applyGraphicsPreset(GraphicsPreset preset);
|
||||||
|
void updateGraphicsPresetFromCurrentSettings();
|
||||||
void renderQuestMarkers(game::GameHandler& gameHandler);
|
void renderQuestMarkers(game::GameHandler& gameHandler);
|
||||||
void renderMinimapMarkers(game::GameHandler& gameHandler);
|
void renderMinimapMarkers(game::GameHandler& gameHandler);
|
||||||
void renderQuestObjectiveTracker(game::GameHandler& gameHandler);
|
void renderQuestObjectiveTracker(game::GameHandler& gameHandler);
|
||||||
|
|
|
||||||
|
|
@ -8595,16 +8595,37 @@ void GameScreen::renderSettingsWindow() {
|
||||||
if (ImGui::BeginTabItem("Video")) {
|
if (ImGui::BeginTabItem("Video")) {
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// Graphics Quality Presets
|
||||||
|
{
|
||||||
|
const char* presetLabels[] = { "Custom", "Low", "Medium", "High", "Ultra" };
|
||||||
|
int presetIdx = static_cast<int>(pendingGraphicsPreset);
|
||||||
|
if (ImGui::Combo("Quality Preset", &presetIdx, presetLabels, 5)) {
|
||||||
|
pendingGraphicsPreset = static_cast<GraphicsPreset>(presetIdx);
|
||||||
|
if (pendingGraphicsPreset != GraphicsPreset::CUSTOM) {
|
||||||
|
applyGraphicsPreset(pendingGraphicsPreset);
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::TextDisabled("Adjust these for custom settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
if (ImGui::Checkbox("Fullscreen", &pendingFullscreen)) {
|
if (ImGui::Checkbox("Fullscreen", &pendingFullscreen)) {
|
||||||
window->setFullscreen(pendingFullscreen);
|
window->setFullscreen(pendingFullscreen);
|
||||||
|
updateGraphicsPresetFromCurrentSettings();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
if (ImGui::Checkbox("VSync", &pendingVsync)) {
|
if (ImGui::Checkbox("VSync", &pendingVsync)) {
|
||||||
window->setVsync(pendingVsync);
|
window->setVsync(pendingVsync);
|
||||||
|
updateGraphicsPresetFromCurrentSettings();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
if (ImGui::Checkbox("Shadows", &pendingShadows)) {
|
if (ImGui::Checkbox("Shadows", &pendingShadows)) {
|
||||||
if (renderer) renderer->setShadowsEnabled(pendingShadows);
|
if (renderer) renderer->setShadowsEnabled(pendingShadows);
|
||||||
|
updateGraphicsPresetFromCurrentSettings();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
if (pendingShadows) {
|
if (pendingShadows) {
|
||||||
|
|
@ -8612,6 +8633,7 @@ void GameScreen::renderSettingsWindow() {
|
||||||
ImGui::SetNextItemWidth(150.0f);
|
ImGui::SetNextItemWidth(150.0f);
|
||||||
if (ImGui::SliderFloat("Distance##shadow", &pendingShadowDistance, 40.0f, 500.0f, "%.0f")) {
|
if (ImGui::SliderFloat("Distance##shadow", &pendingShadowDistance, 40.0f, 500.0f, "%.0f")) {
|
||||||
if (renderer) renderer->setShadowDistance(pendingShadowDistance);
|
if (renderer) renderer->setShadowDistance(pendingShadowDistance);
|
||||||
|
updateGraphicsPresetFromCurrentSettings();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8643,6 +8665,7 @@ void GameScreen::renderSettingsWindow() {
|
||||||
VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT
|
VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT
|
||||||
};
|
};
|
||||||
if (renderer) renderer->setMsaaSamples(aaSamples[pendingAntiAliasing]);
|
if (renderer) renderer->setMsaaSamples(aaSamples[pendingAntiAliasing]);
|
||||||
|
updateGraphicsPresetFromCurrentSettings();
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9426,6 +9449,175 @@ void GameScreen::renderSettingsWindow() {
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameScreen::applyGraphicsPreset(GraphicsPreset preset) {
|
||||||
|
auto* renderer = core::Application::getInstance().getRenderer();
|
||||||
|
|
||||||
|
// Define preset values based on quality level
|
||||||
|
switch (preset) {
|
||||||
|
case GraphicsPreset::LOW: {
|
||||||
|
pendingShadows = false;
|
||||||
|
pendingShadowDistance = 100.0f;
|
||||||
|
pendingAntiAliasing = 0; // Off
|
||||||
|
pendingNormalMapping = false;
|
||||||
|
pendingPOM = false;
|
||||||
|
pendingGroundClutterDensity = 25;
|
||||||
|
if (renderer) {
|
||||||
|
renderer->setShadowsEnabled(false);
|
||||||
|
renderer->setMsaaSamples(VK_SAMPLE_COUNT_1_BIT);
|
||||||
|
if (auto* wr = renderer->getWMORenderer()) {
|
||||||
|
wr->setNormalMappingEnabled(false);
|
||||||
|
wr->setPOMEnabled(false);
|
||||||
|
}
|
||||||
|
if (auto* cr = renderer->getCharacterRenderer()) {
|
||||||
|
cr->setNormalMappingEnabled(false);
|
||||||
|
cr->setPOMEnabled(false);
|
||||||
|
}
|
||||||
|
if (auto* tm = renderer->getTerrainManager()) {
|
||||||
|
tm->setGroundClutterDensityScale(0.25f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GraphicsPreset::MEDIUM: {
|
||||||
|
pendingShadows = true;
|
||||||
|
pendingShadowDistance = 200.0f;
|
||||||
|
pendingAntiAliasing = 1; // 2x MSAA
|
||||||
|
pendingNormalMapping = true;
|
||||||
|
pendingNormalMapStrength = 0.6f;
|
||||||
|
pendingPOM = true;
|
||||||
|
pendingPOMQuality = 0; // Low
|
||||||
|
pendingGroundClutterDensity = 60;
|
||||||
|
if (renderer) {
|
||||||
|
renderer->setShadowsEnabled(true);
|
||||||
|
renderer->setShadowDistance(200.0f);
|
||||||
|
renderer->setMsaaSamples(VK_SAMPLE_COUNT_2_BIT);
|
||||||
|
if (auto* wr = renderer->getWMORenderer()) {
|
||||||
|
wr->setNormalMappingEnabled(true);
|
||||||
|
wr->setNormalMapStrength(0.6f);
|
||||||
|
wr->setPOMEnabled(true);
|
||||||
|
wr->setPOMQuality(0);
|
||||||
|
}
|
||||||
|
if (auto* cr = renderer->getCharacterRenderer()) {
|
||||||
|
cr->setNormalMappingEnabled(true);
|
||||||
|
cr->setNormalMapStrength(0.6f);
|
||||||
|
cr->setPOMEnabled(true);
|
||||||
|
cr->setPOMQuality(0);
|
||||||
|
}
|
||||||
|
if (auto* tm = renderer->getTerrainManager()) {
|
||||||
|
tm->setGroundClutterDensityScale(0.60f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GraphicsPreset::HIGH: {
|
||||||
|
pendingShadows = true;
|
||||||
|
pendingShadowDistance = 350.0f;
|
||||||
|
pendingAntiAliasing = 2; // 4x MSAA
|
||||||
|
pendingNormalMapping = true;
|
||||||
|
pendingNormalMapStrength = 0.8f;
|
||||||
|
pendingPOM = true;
|
||||||
|
pendingPOMQuality = 1; // Medium
|
||||||
|
pendingGroundClutterDensity = 100;
|
||||||
|
if (renderer) {
|
||||||
|
renderer->setShadowsEnabled(true);
|
||||||
|
renderer->setShadowDistance(350.0f);
|
||||||
|
renderer->setMsaaSamples(VK_SAMPLE_COUNT_4_BIT);
|
||||||
|
if (auto* wr = renderer->getWMORenderer()) {
|
||||||
|
wr->setNormalMappingEnabled(true);
|
||||||
|
wr->setNormalMapStrength(0.8f);
|
||||||
|
wr->setPOMEnabled(true);
|
||||||
|
wr->setPOMQuality(1);
|
||||||
|
}
|
||||||
|
if (auto* cr = renderer->getCharacterRenderer()) {
|
||||||
|
cr->setNormalMappingEnabled(true);
|
||||||
|
cr->setNormalMapStrength(0.8f);
|
||||||
|
cr->setPOMEnabled(true);
|
||||||
|
cr->setPOMQuality(1);
|
||||||
|
}
|
||||||
|
if (auto* tm = renderer->getTerrainManager()) {
|
||||||
|
tm->setGroundClutterDensityScale(1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GraphicsPreset::ULTRA: {
|
||||||
|
pendingShadows = true;
|
||||||
|
pendingShadowDistance = 500.0f;
|
||||||
|
pendingAntiAliasing = 3; // 8x MSAA
|
||||||
|
pendingNormalMapping = true;
|
||||||
|
pendingNormalMapStrength = 1.2f;
|
||||||
|
pendingPOM = true;
|
||||||
|
pendingPOMQuality = 2; // High
|
||||||
|
pendingGroundClutterDensity = 150;
|
||||||
|
if (renderer) {
|
||||||
|
renderer->setShadowsEnabled(true);
|
||||||
|
renderer->setShadowDistance(500.0f);
|
||||||
|
renderer->setMsaaSamples(VK_SAMPLE_COUNT_8_BIT);
|
||||||
|
if (auto* wr = renderer->getWMORenderer()) {
|
||||||
|
wr->setNormalMappingEnabled(true);
|
||||||
|
wr->setNormalMapStrength(1.2f);
|
||||||
|
wr->setPOMEnabled(true);
|
||||||
|
wr->setPOMQuality(2);
|
||||||
|
}
|
||||||
|
if (auto* cr = renderer->getCharacterRenderer()) {
|
||||||
|
cr->setNormalMappingEnabled(true);
|
||||||
|
cr->setNormalMapStrength(1.2f);
|
||||||
|
cr->setPOMEnabled(true);
|
||||||
|
cr->setPOMQuality(2);
|
||||||
|
}
|
||||||
|
if (auto* tm = renderer->getTerrainManager()) {
|
||||||
|
tm->setGroundClutterDensityScale(1.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentGraphicsPreset = preset;
|
||||||
|
pendingGraphicsPreset = preset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameScreen::updateGraphicsPresetFromCurrentSettings() {
|
||||||
|
// Check if current settings match any preset, otherwise mark as CUSTOM
|
||||||
|
// This is a simplified check; could be enhanced with more detailed matching
|
||||||
|
|
||||||
|
auto matchesPreset = [this](GraphicsPreset preset) -> bool {
|
||||||
|
switch (preset) {
|
||||||
|
case GraphicsPreset::LOW:
|
||||||
|
return !pendingShadows && pendingAntiAliasing == 0 && !pendingNormalMapping && !pendingPOM &&
|
||||||
|
pendingGroundClutterDensity <= 30;
|
||||||
|
case GraphicsPreset::MEDIUM:
|
||||||
|
return pendingShadows && pendingShadowDistance >= 180 && pendingShadowDistance <= 220 &&
|
||||||
|
pendingAntiAliasing == 1 && pendingNormalMapping && pendingPOM &&
|
||||||
|
pendingGroundClutterDensity >= 50 && pendingGroundClutterDensity <= 70;
|
||||||
|
case GraphicsPreset::HIGH:
|
||||||
|
return pendingShadows && pendingShadowDistance >= 330 && pendingShadowDistance <= 370 &&
|
||||||
|
pendingAntiAliasing == 2 && pendingNormalMapping && pendingPOM &&
|
||||||
|
pendingGroundClutterDensity >= 90 && pendingGroundClutterDensity <= 110;
|
||||||
|
case GraphicsPreset::ULTRA:
|
||||||
|
return pendingShadows && pendingShadowDistance >= 480 && pendingAntiAliasing == 3 &&
|
||||||
|
pendingNormalMapping && pendingPOM && pendingGroundClutterDensity >= 140;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try to match a preset, otherwise mark as custom
|
||||||
|
if (matchesPreset(GraphicsPreset::LOW)) {
|
||||||
|
pendingGraphicsPreset = GraphicsPreset::LOW;
|
||||||
|
} else if (matchesPreset(GraphicsPreset::MEDIUM)) {
|
||||||
|
pendingGraphicsPreset = GraphicsPreset::MEDIUM;
|
||||||
|
} else if (matchesPreset(GraphicsPreset::HIGH)) {
|
||||||
|
pendingGraphicsPreset = GraphicsPreset::HIGH;
|
||||||
|
} else if (matchesPreset(GraphicsPreset::ULTRA)) {
|
||||||
|
pendingGraphicsPreset = GraphicsPreset::ULTRA;
|
||||||
|
} else {
|
||||||
|
pendingGraphicsPreset = GraphicsPreset::CUSTOM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GameScreen::renderQuestMarkers(game::GameHandler& gameHandler) {
|
void GameScreen::renderQuestMarkers(game::GameHandler& gameHandler) {
|
||||||
const auto& statuses = gameHandler.getNpcQuestStatuses();
|
const auto& statuses = gameHandler.getNpcQuestStatuses();
|
||||||
if (statuses.empty()) return;
|
if (statuses.empty()) return;
|
||||||
|
|
@ -10154,6 +10346,7 @@ void GameScreen::saveSettings() {
|
||||||
|
|
||||||
// Gameplay
|
// Gameplay
|
||||||
out << "auto_loot=" << (pendingAutoLoot ? 1 : 0) << "\n";
|
out << "auto_loot=" << (pendingAutoLoot ? 1 : 0) << "\n";
|
||||||
|
out << "graphics_preset=" << static_cast<int>(currentGraphicsPreset) << "\n";
|
||||||
out << "ground_clutter_density=" << pendingGroundClutterDensity << "\n";
|
out << "ground_clutter_density=" << pendingGroundClutterDensity << "\n";
|
||||||
out << "shadows=" << (pendingShadows ? 1 : 0) << "\n";
|
out << "shadows=" << (pendingShadows ? 1 : 0) << "\n";
|
||||||
out << "shadow_distance=" << pendingShadowDistance << "\n";
|
out << "shadow_distance=" << pendingShadowDistance << "\n";
|
||||||
|
|
@ -10267,6 +10460,11 @@ void GameScreen::loadSettings() {
|
||||||
else if (key == "activity_volume") pendingActivityVolume = std::clamp(std::stoi(val), 0, 100);
|
else if (key == "activity_volume") pendingActivityVolume = std::clamp(std::stoi(val), 0, 100);
|
||||||
// Gameplay
|
// Gameplay
|
||||||
else if (key == "auto_loot") pendingAutoLoot = (std::stoi(val) != 0);
|
else if (key == "auto_loot") pendingAutoLoot = (std::stoi(val) != 0);
|
||||||
|
else if (key == "graphics_preset") {
|
||||||
|
int presetVal = std::clamp(std::stoi(val), 0, 4);
|
||||||
|
currentGraphicsPreset = static_cast<GraphicsPreset>(presetVal);
|
||||||
|
pendingGraphicsPreset = currentGraphicsPreset;
|
||||||
|
}
|
||||||
else if (key == "ground_clutter_density") pendingGroundClutterDensity = std::clamp(std::stoi(val), 0, 150);
|
else if (key == "ground_clutter_density") pendingGroundClutterDensity = std::clamp(std::stoi(val), 0, 150);
|
||||||
else if (key == "shadows") pendingShadows = (std::stoi(val) != 0);
|
else if (key == "shadows") pendingShadows = (std::stoi(val) != 0);
|
||||||
else if (key == "shadow_distance") pendingShadowDistance = std::clamp(std::stof(val), 40.0f, 500.0f);
|
else if (key == "shadow_distance") pendingShadowDistance = std::clamp(std::stof(val), 40.0f, 500.0f);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue