aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCamilleLaVey <camillelavey99@gmail.com>2026-09-15 07:23:12 +0200
committercrueter <crueter@eden-emu.dev>2026-09-15 07:23:12 +0200
commitc5405250d179824cdcd55d2dbd0a484f516490af (patch)
tree8ebf2da460cde4bf584c64de712e3b48bf6d7fcf /src
parent10c07d700c33fa1ff78d5f616c2da2872fc5d43f (diff)
[common, ui] Refining UI for FX shaders for PC (#4426)
Self-explanatory refinements on the already existing access/usage of post-processing shaders on Eden for PC UI. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4426 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: lizzie <lizzie@eden-emu.dev>
Diffstat (limited to 'src')
-rw-r--r--src/qt_common/config/shared_translation.cpp3
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp27
-rw-r--r--src/yuzu/configuration/configure_post_processing.cpp36
-rw-r--r--src/yuzu/main_window.cpp57
-rw-r--r--src/yuzu/main_window.h2
5 files changed, 110 insertions, 15 deletions
diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp
index 0db439691f..4ef97c602a 100644
--- a/src/qt_common/config/shared_translation.cpp
+++ b/src/qt_common/config/shared_translation.cpp
@@ -151,6 +151,9 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA "
"can produce a more stable picture in lower resolutions."));
INSERT(Settings, post_shader_chain, QString(), QString());
+ INSERT(Settings, post_shader_preset, QString(), QString());
+ INSERT(Settings, post_shader_enabled, tr("Enable post-processing effects"),
+ tr("Applies post-processing effects to the final image."));
INSERT(Settings, fullscreen_mode, tr("Fullscreen Mode:"),
tr("The method used to render the window in fullscreen.\nBorderless offers the best "
"compatibility with the on-screen keyboard that some games request for "
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index f294403397..641f65d82a 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -37,6 +37,10 @@
#include "yuzu/configuration/configure_graphics.h"
#include "yuzu/configuration/shared_widget.h"
+#ifdef HAS_RESHADE
+#include "yuzu/configuration/configure_post_processing.h"
+#endif
+
ConfigureGraphics::ConfigureGraphics(
const Core::System& system_, std::vector<VkDeviceInfo::Record>& records_,
const std::function<void()>& expose_compute_option_,
@@ -216,6 +220,12 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
std::vector<QWidget*> hold_api;
for (const auto setting : Settings::values.linkage.by_category[Settings::Category::Renderer]) {
+#ifndef HAS_RESHADE
+ if (setting->Id() == Settings::values.post_shader_enabled.Id()) {
+ continue;
+ }
+#endif
+
ConfigurationShared::Widget* widget = [&]() {
if (setting->Id() == Settings::values.fsr_sharpening_slider.Id()) {
// FSR needs a reversed slider and a 0.5 multiplier
@@ -295,6 +305,23 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
// Keep track of the resolution combobox to update other UI tabs that need it
resolution_combobox = widget->combobox;
hold_graphics.emplace(setting->Id(), widget);
+#ifdef HAS_RESHADE
+ } else if (setting->Id() == Settings::values.post_shader_enabled.Id()) {
+ QPushButton* post_shader_button = new QPushButton(tr("Configure Effects..."), widget);
+ post_shader_button->setVisible(widget->checkbox->isChecked());
+
+ connect(post_shader_button, &QAbstractButton::clicked, this, [this]() {
+ ConfigurePostProcessing dialog(this);
+ dialog.exec();
+ });
+ connect(widget->checkbox, &QCheckBox::toggled, post_shader_button,
+ &QWidget::setVisible);
+
+ QBoxLayout* row = qobject_cast<QBoxLayout*>(widget->layout());
+ row->insertWidget(1, post_shader_button);
+
+ hold_graphics.emplace(setting->Id(), widget);
+#endif
} else {
hold_graphics.emplace(setting->Id(), widget);
}
diff --git a/src/yuzu/configuration/configure_post_processing.cpp b/src/yuzu/configuration/configure_post_processing.cpp
index 6fe46da6c5..659c3618f2 100644
--- a/src/yuzu/configuration/configure_post_processing.cpp
+++ b/src/yuzu/configuration/configure_post_processing.cpp
@@ -70,10 +70,8 @@ ConfigurePostProcessing::ConfigurePostProcessing(QWidget* parent) : QDialog(pare
auto* root = new QVBoxLayout(this);
- auto* description = new QLabel(
- tr("ReShade FX effects are loaded from the post_shaders folder in the Eden data "
- "directory. Changes apply immediately while a game is running."),
- this);
+ auto* description =
+ new QLabel(tr("Changes apply immediately while a game is running."), this);
description->setWordWrap(true);
root->addWidget(description);
@@ -128,17 +126,15 @@ ConfigurePostProcessing::ConfigurePostProcessing(QWidget* parent) : QDialog(pare
});
preset_row->addWidget(save_button);
- auto* delete_button = new QPushButton(tr("Delete"), this);
- connect(delete_button, &QPushButton::clicked, this, [this]() {
- const QString name = preset_combo->currentData().toString();
- if (name.isEmpty()) {
- return;
- }
- VideoCore::DeleteFxPreset(name.toStdString());
- PopulatePresetCombo();
- RefreshPresetStatus();
+ auto* clear_button = new QPushButton(tr("Clear"), this);
+ clear_button->setToolTip(tr("Remove every effect in use and deselect the preset."));
+ connect(clear_button, &QPushButton::clicked, this, [this]() {
+ VideoCore::FxChain::Instance().Clear();
+ VideoCore::SetActiveFxPreset(std::string());
+ preset_combo->setCurrentIndex(0);
+ ApplyStructuralChange();
});
- preset_row->addWidget(delete_button);
+ preset_row->addWidget(clear_button);
root->addLayout(preset_row);
@@ -203,6 +199,7 @@ void ConfigurePostProcessing::ApplyStructuralChange() {
void ConfigurePostProcessing::PopulatePresetCombo() {
const QString previous = preset_combo->currentData().toString();
preset_combo->clear();
+ preset_combo->addItem(tr("None"), QString());
for (const auto& preset : VideoCore::GetFxPresetCatalog()) {
const QString name = QString::fromStdString(preset.name);
@@ -212,7 +209,7 @@ void ConfigurePostProcessing::PopulatePresetCombo() {
}
const int restored = preset_combo->findData(previous);
- if (restored >= 0) {
+ if (!previous.isEmpty() && restored >= 0) {
preset_combo->setCurrentIndex(restored);
return;
}
@@ -220,12 +217,21 @@ void ConfigurePostProcessing::PopulatePresetCombo() {
const int active = preset_combo->findData(QString::fromStdString(VideoCore::GetActiveFxPreset()));
if (active >= 0) {
preset_combo->setCurrentIndex(active);
+ return;
}
+
+ preset_combo->setCurrentIndex(0);
}
void ConfigurePostProcessing::RefreshPresetStatus() {
const std::string active = VideoCore::GetActiveFxPreset();
if (active.empty()) {
+ if (VideoCore::FxChain::Instance().Size() == 0) {
+ preset_status->setText(
+ tr("No effects in use. Pick a preset and press Apply, or add effects one "
+ "by one."));
+ return;
+ }
preset_status->setText(tr("Custom chain. Pick a preset above and press Apply to replace it."));
return;
}
diff --git a/src/yuzu/main_window.cpp b/src/yuzu/main_window.cpp
index 95b91a4f38..1d579239a1 100644
--- a/src/yuzu/main_window.cpp
+++ b/src/yuzu/main_window.cpp
@@ -15,6 +15,7 @@
#include "render/performance_overlay.h"
#ifdef HAS_RESHADE
#include "configuration/configure_post_processing.h"
+#include "video_core/post_processing/fx_preset.h"
#endif
#include "updater/update_dialog.h"
@@ -1090,6 +1091,41 @@ void MainWindow::InitializeWidgets() {
statusBar()->insertPermanentWidget(0, volume_button);
+#ifdef HAS_RESHADE
+ post_shader_status_button = new QPushButton();
+ post_shader_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
+ post_shader_status_button->setFocusPolicy(Qt::NoFocus);
+ post_shader_status_button->setCheckable(true);
+ connect(post_shader_status_button, &QPushButton::clicked, this, [this] {
+ const bool enabled = Settings::values.post_shader_enabled.GetValue();
+ Settings::values.post_shader_enabled.SetValue(!enabled);
+ UpdatePostShaderText();
+ });
+ UpdatePostShaderText();
+ post_shader_status_button->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(post_shader_status_button, &QPushButton::customContextMenuRequested,
+ [this](const QPoint& menu_location) {
+ QMenu context_menu;
+
+ for (auto const& preset : VideoCore::GetFxPresetCatalog()) {
+ context_menu.addAction(QString::fromStdString(preset.name),
+ [this, name = preset.name] {
+ VideoCore::ApplyFxPreset(name);
+ Settings::values.post_shader_enabled.SetValue(true);
+ UpdatePostShaderText();
+ });
+ }
+
+ context_menu.addSeparator();
+ context_menu.addAction(tr("Configure Effects..."), this,
+ &MainWindow::OnPostProcessingShaders);
+
+ context_menu.exec(post_shader_status_button->mapToGlobal(menu_location));
+ post_shader_status_button->repaint();
+ });
+ statusBar()->insertPermanentWidget(0, post_shader_status_button);
+#endif
+
// setup AA button
aa_status_button = new QPushButton();
aa_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
@@ -3908,6 +3944,7 @@ void MainWindow::OnPostProcessingShaders() {
connect(post_processing_dialog, &QDialog::finished, post_processing_dialog, [this]() {
post_processing_dialog->deleteLater();
post_processing_dialog = nullptr;
+ UpdatePostShaderText();
});
}
@@ -4262,6 +4299,26 @@ void MainWindow::UpdateAAText() {
: aa_text.toUpper());
}
+#ifdef HAS_RESHADE
+void MainWindow::UpdatePostShaderText() {
+ const bool enabled = Settings::values.post_shader_enabled.GetValue();
+ post_shader_status_button->setChecked(enabled);
+
+ if (!enabled) {
+ post_shader_status_button->setText(tr("NO FX"));
+ return;
+ }
+
+ const std::string preset = VideoCore::GetActiveFxPreset();
+ if (preset.empty()) {
+ post_shader_status_button->setText(tr("FX"));
+ return;
+ }
+
+ post_shader_status_button->setText(QString::fromStdString(preset).toUpper());
+}
+#endif
+
void MainWindow::UpdateVolumeUI() {
const auto volume_value = static_cast<int>(Settings::values.volume.GetValue());
volume_slider->setValue(volume_value);
diff --git a/src/yuzu/main_window.h b/src/yuzu/main_window.h
index 2e92df135d..8aedeec721 100644
--- a/src/yuzu/main_window.h
+++ b/src/yuzu/main_window.h
@@ -448,6 +448,7 @@ private:
void UpdateAPIText();
void UpdateFilterText();
void UpdateAAText();
+ void UpdatePostShaderText();
void UpdateVolumeUI();
void UpdateStatusBar();
void UpdateGPUAccuracyButton();
@@ -524,6 +525,7 @@ private:
QPushButton* dock_status_button = nullptr;
QPushButton* filter_status_button = nullptr;
QPushButton* aa_status_button = nullptr;
+ QPushButton* post_shader_status_button = nullptr;
VolumeButton* volume_button = nullptr;
QWidget* volume_popup = nullptr;
QSlider* volume_slider = nullptr;