GPU: Add alpha blending support to overlay
This commit is contained in:
parent
9b8d2a88de
commit
9fdeeb3fb6
|
@ -4,3 +4,4 @@ displayStartY: 260
|
|||
displayEndX: 2850
|
||||
displayEndY: 1655
|
||||
alphaBlend: false
|
||||
destinationAlphaBlend: false
|
||||
|
|
|
@ -5771,10 +5771,15 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
|||
FSUI_CSTR("Determines the area of the overlay image that the display will be drawn within."), "BorderOverlay",
|
||||
"DisplayStartX", 0, "DisplayStartY", 0, "DisplayEndX", 0, "DisplayEndY", 0, 0, 65535, "%dpx");
|
||||
|
||||
reload_pending |=
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BLENDER, "Alpha Blending"),
|
||||
FSUI_CSTR("If enabled, the transparency of the overlay image will be applied."),
|
||||
"BorderOverlay", "AlphaBlend", false);
|
||||
|
||||
reload_pending |= DrawToggleSetting(
|
||||
bsi, FSUI_ICONSTR(ICON_FA_BLENDER, "Destination Alpha Blending"),
|
||||
FSUI_CSTR("If enabled, the display will be blended with the transparency of the overlay image."),
|
||||
"BorderOverlay", "AlphaBlend", false);
|
||||
"BorderOverlay", "DestinationAlphaBlend", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8660,6 +8665,7 @@ TRANSLATE_NOOP("FullscreenUI", "Advanced Settings");
|
|||
TRANSLATE_NOOP("FullscreenUI", "All Time: {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Allow Booting Without SBI File");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Allows loading protected games without subchannel information.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Alpha Blending");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Always Track Uploads");
|
||||
TRANSLATE_NOOP("FullscreenUI", "An error occurred while deleting empty game settings:\n{}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "An error occurred while saving game settings:\n{}");
|
||||
|
@ -8925,6 +8931,7 @@ TRANSLATE_NOOP("FullscreenUI", "How many saves will be kept for rewinding. Highe
|
|||
TRANSLATE_NOOP("FullscreenUI", "How often a rewind state will be created. Higher frequencies have greater system requirements.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Identifies any new files added to the game directories.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "If enabled, the display will be blended with the transparency of the overlay image.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "If enabled, the transparency of the overlay image will be applied.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "If not enabled, the current post processing chain will be ignored.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Image Path");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Increases the field of view from 4:3 to the chosen display aspect ratio in 3D games.");
|
||||
|
|
|
@ -153,66 +153,69 @@ bool GPUPresenter::CompileDisplayPipelines(bool display, bool deinterlace, bool
|
|||
GL_OBJECT_NAME_FMT(m_display_pipeline, "Display Pipeline [{}]",
|
||||
Settings::GetDisplayScalingName(g_gpu_settings.display_scaling));
|
||||
|
||||
std::unique_ptr<GPUShader> rotate_copy_fso = g_gpu_device->CreateShader(
|
||||
std::unique_ptr<GPUShader> copy_fso = g_gpu_device->CreateShader(
|
||||
GPUShaderStage::Fragment, shadergen.GetLanguage(), shadergen.GenerateCopyFragmentShader(false), error);
|
||||
if (!rotate_copy_fso)
|
||||
if (!copy_fso)
|
||||
return false;
|
||||
GL_OBJECT_NAME(rotate_copy_fso, "Display Rotate/Copy Fragment Shader");
|
||||
GL_OBJECT_NAME(copy_fso, "Display Copy Fragment Shader");
|
||||
|
||||
plconfig.fragment_shader = rotate_copy_fso.get();
|
||||
plconfig.fragment_shader = copy_fso.get();
|
||||
if (!(m_present_copy_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
return false;
|
||||
GL_OBJECT_NAME(m_present_copy_pipeline, "Display Rotate/Copy Pipeline");
|
||||
GL_OBJECT_NAME(m_present_copy_pipeline, "Display Copy Pipeline");
|
||||
|
||||
// blended variants
|
||||
if (m_border_overlay_texture)
|
||||
{
|
||||
std::unique_ptr<GPUShader> clear_fso =
|
||||
g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(),
|
||||
shadergen.GenerateFillFragmentShader(GSVector4i::zero()), error);
|
||||
std::unique_ptr<GPUShader> clear_fso = g_gpu_device->CreateShader(
|
||||
GPUShaderStage::Fragment, shadergen.GetLanguage(),
|
||||
shadergen.GenerateFillFragmentShader(GSVector4::cxpr(0.0f, 0.0f, 0.0f, 1.0f)), error);
|
||||
if (!clear_fso)
|
||||
return false;
|
||||
GL_OBJECT_NAME(clear_fso, "Display Clear Fragment Shader");
|
||||
|
||||
plconfig.fragment_shader = clear_fso.get();
|
||||
if (!(m_present_clear_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
plconfig.fragment_shader = copy_fso.get();
|
||||
plconfig.blend = m_border_overlay_alpha_blend ? GPUPipeline::BlendState::GetAlphaBlendingState() :
|
||||
GPUPipeline::BlendState::GetNoBlendingState();
|
||||
if (!(m_border_overlay_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
return false;
|
||||
GL_OBJECT_NAME(m_present_clear_pipeline, "Display Clear Pipeline");
|
||||
GL_OBJECT_NAME(m_border_overlay_pipeline, "Border Overlay Pipeline");
|
||||
|
||||
if (m_border_overlay_alpha_blend)
|
||||
plconfig.blend = GPUPipeline::BlendState::GetNoBlendingState();
|
||||
if (m_border_overlay_destination_alpha_blend)
|
||||
{
|
||||
// destination blend the main present, not source
|
||||
plconfig.blend.enable = true;
|
||||
plconfig.blend.src_blend = GPUPipeline::BlendFunc::InvDstAlpha;
|
||||
plconfig.blend.blend_op = GPUPipeline::BlendOp::Add;
|
||||
plconfig.blend.dst_blend = GPUPipeline::BlendFunc::One;
|
||||
plconfig.blend.src_alpha_blend = GPUPipeline::BlendFunc::One;
|
||||
plconfig.blend.src_alpha_blend = GPUPipeline::BlendFunc::Zero;
|
||||
plconfig.blend.alpha_blend_op = GPUPipeline::BlendOp::Add;
|
||||
plconfig.blend.dst_alpha_blend = GPUPipeline::BlendFunc::Zero;
|
||||
|
||||
plconfig.fragment_shader = fso.get();
|
||||
if (!(m_display_blend_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
return false;
|
||||
GL_OBJECT_NAME_FMT(m_display_blend_pipeline, "Display Pipeline [Blended, {}]",
|
||||
Settings::GetDisplayScalingName(g_gpu_settings.display_scaling));
|
||||
|
||||
plconfig.fragment_shader = rotate_copy_fso.get();
|
||||
if (!(m_present_copy_blend_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
return false;
|
||||
GL_OBJECT_NAME(m_present_copy_blend_pipeline, "Display Rotate/Copy Pipeline [Blended]");
|
||||
|
||||
plconfig.fragment_shader = clear_fso.get();
|
||||
if (!(m_present_clear_blend_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
return false;
|
||||
GL_OBJECT_NAME(m_present_clear_blend_pipeline, "Display Clear Pipeline [Blended]");
|
||||
plconfig.blend.dst_alpha_blend = GPUPipeline::BlendFunc::One;
|
||||
}
|
||||
|
||||
plconfig.fragment_shader = clear_fso.get();
|
||||
if (!(m_present_clear_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
return false;
|
||||
GL_OBJECT_NAME(m_present_clear_pipeline, "Display Clear Pipeline");
|
||||
|
||||
plconfig.fragment_shader = fso.get();
|
||||
if (!(m_display_blend_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
return false;
|
||||
GL_OBJECT_NAME_FMT(m_display_blend_pipeline, "Display Pipeline [Blended, {}]",
|
||||
Settings::GetDisplayScalingName(g_gpu_settings.display_scaling));
|
||||
|
||||
plconfig.fragment_shader = copy_fso.get();
|
||||
if (!(m_present_copy_blend_pipeline = g_gpu_device->CreatePipeline(plconfig, error)))
|
||||
return false;
|
||||
GL_OBJECT_NAME(m_present_copy_blend_pipeline, "Display Copy Pipeline [Blended]");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_border_overlay_pipeline.reset();
|
||||
m_present_clear_pipeline.reset();
|
||||
m_display_blend_pipeline.reset();
|
||||
m_present_copy_blend_pipeline.reset();
|
||||
m_present_clear_blend_pipeline.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -483,13 +486,12 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
|
|||
if (have_overlay)
|
||||
{
|
||||
GL_SCOPE_FMT("Draw overlay and postfx buffer");
|
||||
g_gpu_device->SetPipeline(m_present_copy_pipeline.get());
|
||||
g_gpu_device->SetPipeline(m_border_overlay_pipeline.get());
|
||||
g_gpu_device->SetTextureSampler(0, m_border_overlay_texture.get(), g_gpu_device->GetLinearSampler());
|
||||
DrawScreenQuad(overlay_rect, GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), target_size, DisplayRotation::Normal,
|
||||
prerotation);
|
||||
|
||||
g_gpu_device->SetPipeline(m_border_overlay_alpha_blend ? m_present_copy_blend_pipeline.get() :
|
||||
m_present_copy_pipeline.get());
|
||||
g_gpu_device->SetPipeline(m_border_overlay_pipeline.get());
|
||||
g_gpu_device->SetTextureSampler(0, postfx_output, g_gpu_device->GetNearestSampler());
|
||||
DrawScreenQuad(overlay_display_rect, GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), target_size,
|
||||
DisplayRotation::Normal, prerotation);
|
||||
|
@ -523,7 +525,7 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
|
|||
if (have_overlay)
|
||||
{
|
||||
GL_SCOPE_FMT("Draw overlay to {}", overlay_rect);
|
||||
g_gpu_device->SetPipeline(m_present_copy_pipeline.get());
|
||||
g_gpu_device->SetPipeline(m_border_overlay_pipeline.get());
|
||||
g_gpu_device->SetTextureSampler(0, m_border_overlay_texture.get(), g_gpu_device->GetLinearSampler());
|
||||
|
||||
DrawScreenQuad(overlay_rect, GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), target_size, DisplayRotation::Normal,
|
||||
|
@ -533,15 +535,14 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
|
|||
{
|
||||
// Need to fill in the borders.
|
||||
GL_SCOPE_FMT("Fill in overlay borders - odisplay={}, draw={}", overlay_display_rect, draw_rect);
|
||||
g_gpu_device->SetPipeline(m_border_overlay_alpha_blend ? m_present_clear_blend_pipeline.get() :
|
||||
m_present_clear_pipeline.get());
|
||||
g_gpu_device->SetPipeline(m_present_clear_pipeline.get());
|
||||
DrawScreenQuad(overlay_display_rect, GSVector4::zero(), target_size, g_settings.display_rotation, prerotation);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_display_texture)
|
||||
{
|
||||
DrawDisplay(target_size, display_rect, m_border_overlay_alpha_blend, g_gpu_settings.display_rotation,
|
||||
DrawDisplay(target_size, display_rect, m_border_overlay_destination_alpha_blend, g_gpu_settings.display_rotation,
|
||||
prerotation);
|
||||
}
|
||||
|
||||
|
@ -1127,14 +1128,9 @@ bool GPUPresenter::UpdatePostProcessingSettings(bool force_reload, Error* error)
|
|||
if (LoadOverlaySettings())
|
||||
{
|
||||
// something changed, need to recompile pipelines, the needed pipelines are based on alpha blend
|
||||
if (LoadOverlayTexture() &&
|
||||
((m_border_overlay_alpha_blend &&
|
||||
(!m_present_copy_blend_pipeline || !m_display_blend_pipeline || !m_present_clear_blend_pipeline)) ||
|
||||
!m_present_clear_pipeline) &&
|
||||
!CompileDisplayPipelines(true, false, false, error))
|
||||
{
|
||||
LoadOverlayTexture();
|
||||
if (!CompileDisplayPipelines(true, false, false, error))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Update postfx settings
|
||||
|
@ -1245,6 +1241,7 @@ bool GPUPresenter::LoadOverlaySettings()
|
|||
std::string image_path;
|
||||
GSVector4i display_rect = m_border_overlay_display_rect;
|
||||
bool alpha_blend = m_border_overlay_alpha_blend;
|
||||
bool destination_alpha_blend = m_border_overlay_destination_alpha_blend;
|
||||
if (preset_name == "Custom")
|
||||
{
|
||||
image_path = Host::GetStringSettingValue("BorderOverlay", "ImagePath");
|
||||
|
@ -1253,6 +1250,7 @@ bool GPUPresenter::LoadOverlaySettings()
|
|||
Host::GetIntSettingValue("BorderOverlay", "DisplayEndX", 0),
|
||||
Host::GetIntSettingValue("BorderOverlay", "DisplayEndY", 0));
|
||||
alpha_blend = Host::GetBoolSettingValue("BorderOverlay", "AlphaBlend", false);
|
||||
destination_alpha_blend = Host::GetBoolSettingValue("BorderOverlay", "DestinationAlphaBlend", false);
|
||||
}
|
||||
|
||||
// check rect validity.. ignore everything if it's bogus
|
||||
|
@ -1281,15 +1279,16 @@ bool GPUPresenter::LoadOverlaySettings()
|
|||
m_border_overlay_display_rect = display_rect;
|
||||
|
||||
// but images and alphablend require pipeline/texture changes
|
||||
if (m_border_overlay_image_path == image_path && (image_path.empty() || alpha_blend == m_border_overlay_alpha_blend))
|
||||
{
|
||||
m_border_overlay_alpha_blend = alpha_blend;
|
||||
return false;
|
||||
}
|
||||
const bool image_changed = (m_border_overlay_image_path != image_path);
|
||||
const bool changed =
|
||||
(image_changed || (!image_path.empty() && (alpha_blend == m_border_overlay_alpha_blend ||
|
||||
destination_alpha_blend == m_border_overlay_destination_alpha_blend)));
|
||||
if (image_changed)
|
||||
m_border_overlay_image_path = std::move(image_path);
|
||||
|
||||
m_border_overlay_image_path = std::move(image_path);
|
||||
m_border_overlay_alpha_blend = alpha_blend;
|
||||
return true;
|
||||
m_border_overlay_destination_alpha_blend = destination_alpha_blend;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool GPUPresenter::LoadOverlayTexture()
|
||||
|
@ -1371,13 +1370,15 @@ bool GPUPresenter::LoadOverlayPreset(Error* error, Image* image)
|
|||
|
||||
std::string_view image_filename;
|
||||
GSVector4i display_area = GSVector4i::zero();
|
||||
bool display_alpha_blend = false;
|
||||
bool alpha_blend = false;
|
||||
bool destination_alpha_blend = false;
|
||||
if (!GetStringFromObject(root, "image", &image_filename) ||
|
||||
!GetUIntFromObject(root, "displayStartX", &display_area.x) ||
|
||||
!GetUIntFromObject(root, "displayStartY", &display_area.y) ||
|
||||
!GetUIntFromObject(root, "displayEndX", &display_area.z) ||
|
||||
!GetUIntFromObject(root, "displayEndY", &display_area.w) ||
|
||||
!GetUIntFromObject(root, "alphaBlend", &display_alpha_blend))
|
||||
!GetUIntFromObject(root, "alphaBlend", &alpha_blend) ||
|
||||
!GetUIntFromObject(root, "destinationAlphaBlend", &destination_alpha_blend))
|
||||
{
|
||||
Error::SetStringView(error, "One or more parameters is missing.");
|
||||
return false;
|
||||
|
@ -1389,6 +1390,7 @@ bool GPUPresenter::LoadOverlayPreset(Error* error, Image* image)
|
|||
return false;
|
||||
|
||||
m_border_overlay_display_rect = display_area;
|
||||
m_border_overlay_alpha_blend = display_alpha_blend;
|
||||
m_border_overlay_alpha_blend = alpha_blend;
|
||||
m_border_overlay_destination_alpha_blend = destination_alpha_blend;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -147,17 +147,17 @@ private:
|
|||
u32 m_skipped_present_count = 0;
|
||||
GPUTexture::Format m_present_format = GPUTexture::Format::Unknown;
|
||||
bool m_border_overlay_alpha_blend = false;
|
||||
bool m_border_overlay_destination_alpha_blend = false;
|
||||
|
||||
std::unique_ptr<GPUPipeline> m_present_copy_pipeline;
|
||||
|
||||
std::unique_ptr<PostProcessing::Chain> m_display_postfx;
|
||||
std::unique_ptr<GPUTexture> m_border_overlay_texture;
|
||||
std::unique_ptr<GPUPipeline> m_present_clear_pipeline;
|
||||
|
||||
// blended variants of pipelines, used when overlays are enabled
|
||||
std::unique_ptr<GPUPipeline> m_border_overlay_pipeline;
|
||||
std::unique_ptr<GPUPipeline> m_present_clear_pipeline;
|
||||
std::unique_ptr<GPUPipeline> m_display_blend_pipeline;
|
||||
std::unique_ptr<GPUPipeline> m_present_copy_blend_pipeline;
|
||||
std::unique_ptr<GPUPipeline> m_present_clear_blend_pipeline;
|
||||
|
||||
GSVector4i m_border_overlay_display_rect = GSVector4i::zero();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>540</width>
|
||||
<height>355</height>
|
||||
<height>381</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -115,10 +115,10 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="alphaBlend">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Destination Alpha Blending</string>
|
||||
<string>Display End:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -160,12 +160,47 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Display End:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="1,1">
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="destinationAlphaBlend">
|
||||
<property name="text">
|
||||
<string>Destination Alpha Blending</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="alphaBlend">
|
||||
<property name="text">
|
||||
<string>Alpha Blending</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="exportCustomConfig">
|
||||
<property name="text">
|
||||
<string>Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
|
@ -511,6 +511,8 @@ PostProcessingOverlayConfigWidget::PostProcessingOverlayConfigWidget(SettingsWin
|
|||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.displayEndX, "BorderOverlay", "DisplayEndX", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.displayEndY, "BorderOverlay", "DisplayEndY", 0);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alphaBlend, "BorderOverlay", "AlphaBlend", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.destinationAlphaBlend, "BorderOverlay",
|
||||
"DestinationAlphaBlend", false);
|
||||
|
||||
connect(m_ui.overlayName, &QComboBox::currentIndexChanged, this,
|
||||
&PostProcessingOverlayConfigWidget::onOverlayNameCurrentIndexChanged);
|
||||
|
@ -525,12 +527,36 @@ PostProcessingOverlayConfigWidget::PostProcessingOverlayConfigWidget(SettingsWin
|
|||
connect(m_ui.displayEndY, &QSpinBox::textChanged, this, &PostProcessingOverlayConfigWidget::triggerSettingsReload);
|
||||
connect(m_ui.alphaBlend, &QCheckBox::checkStateChanged, this,
|
||||
&PostProcessingOverlayConfigWidget::triggerSettingsReload);
|
||||
connect(m_ui.destinationAlphaBlend, &QCheckBox::checkStateChanged, this,
|
||||
&PostProcessingOverlayConfigWidget::triggerSettingsReload);
|
||||
|
||||
onOverlayNameCurrentIndexChanged(m_ui.overlayName->currentIndex());
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.imagePath, tr("Image Path"), tr("Unspecified"),
|
||||
tr("Defines the path of the custom overlay image that will be loaded."));
|
||||
const QString display_rect_title = tr("Display Rectangle");
|
||||
const QString display_rect_rec_value = tr("Unspecified");
|
||||
const QString display_rect_help = tr("Defines the area in the overlay image that the game image will be drawn into.");
|
||||
dialog->registerWidgetHelp(m_ui.displayStartX, display_rect_title, display_rect_rec_value, display_rect_help);
|
||||
dialog->registerWidgetHelp(m_ui.displayStartY, display_rect_title, display_rect_rec_value, display_rect_help);
|
||||
dialog->registerWidgetHelp(m_ui.displayEndX, display_rect_title, display_rect_rec_value, display_rect_help);
|
||||
dialog->registerWidgetHelp(m_ui.displayEndY, display_rect_title, display_rect_rec_value, display_rect_help);
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.alphaBlend, tr("Alpha Blending"), tr("Unchecked"),
|
||||
tr("If checked, the overlay image will be alpha blended with the framebuffer, i.e. transparency will be applied."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.destinationAlphaBlend, tr("Destination Alpha Blending"), tr("Unchecked"),
|
||||
tr("If checked, the game image will be blended with the inverse amount of alpha in the overlay image. For example, "
|
||||
"an image with alpha of 0.75 will draw the game image at 25% brightness."));
|
||||
}
|
||||
|
||||
PostProcessingOverlayConfigWidget::~PostProcessingOverlayConfigWidget() = default;
|
||||
|
||||
void PostProcessingOverlayConfigWidget::triggerSettingsReload()
|
||||
{
|
||||
g_emu_thread->updatePostProcessingSettings(true, false, false);
|
||||
}
|
||||
|
||||
void PostProcessingOverlayConfigWidget::onOverlayNameCurrentIndexChanged(int index)
|
||||
{
|
||||
const int custom_idx = m_dialog->isPerGameSettings() ? 2 : 1;
|
||||
|
@ -549,7 +575,33 @@ void PostProcessingOverlayConfigWidget::onImagePathBrowseClicked()
|
|||
m_ui.imagePath->setText(QDir::toNativeSeparators(path));
|
||||
}
|
||||
|
||||
void PostProcessingOverlayConfigWidget::triggerSettingsReload()
|
||||
void PostProcessingOverlayConfigWidget::onExportCustomConfigClicked()
|
||||
{
|
||||
g_emu_thread->updatePostProcessingSettings(true, false, false);
|
||||
const QString path =
|
||||
QFileDialog::getSaveFileName(QtUtils::GetRootWidget(this), tr("Export to YAML"),
|
||||
QFileInfo(m_ui.imagePath->text()).dir().path(), tr("YAML Files (*.yml)"));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
const QString output = QStringLiteral("imagePath: \"%1\"\n"
|
||||
"displayStartX: %2\n"
|
||||
"displayStartY: %3\n"
|
||||
"displayEndX: %4\n"
|
||||
"displayEndY: %5\n"
|
||||
"alphaBlend: %6\n"
|
||||
"destinationAlphaBlend: %7\n")
|
||||
.arg(QFileInfo(m_ui.imagePath->text()).fileName(), m_ui.displayStartX->value())
|
||||
.arg(m_ui.displayStartY->value())
|
||||
.arg(m_ui.displayEndX->value())
|
||||
.arg(m_ui.displayEndY->value())
|
||||
.arg(m_ui.alphaBlend->isChecked() ? "true" : "false")
|
||||
.arg(m_ui.destinationAlphaBlend->isChecked() ? "true" : "false");
|
||||
|
||||
Error error;
|
||||
if (!FileSystem::WriteStringToFile(QDir::toNativeSeparators(path).toStdString().c_str(), output.toStdString(),
|
||||
&error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Export Error"),
|
||||
tr("Failed to save file: %1").arg(QString::fromStdString(error.GetDescription())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,9 +98,10 @@ public:
|
|||
~PostProcessingOverlayConfigWidget();
|
||||
|
||||
private Q_SLOTS:
|
||||
void triggerSettingsReload();
|
||||
void onOverlayNameCurrentIndexChanged(int index);
|
||||
void onImagePathBrowseClicked();
|
||||
void triggerSettingsReload();
|
||||
void onExportCustomConfigClicked();
|
||||
|
||||
private:
|
||||
Ui::PostProcessingOverlayConfigWidget m_ui;
|
||||
|
|
|
@ -845,7 +845,7 @@ std::string ShaderGen::GenerateFillFragmentShader() const
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
std::string ShaderGen::GenerateFillFragmentShader(const GSVector4i fixed_color) const
|
||||
std::string ShaderGen::GenerateFillFragmentShader(const GSVector4 fixed_color) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
WriteHeader(ss);
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
std::string GenerateScreenQuadVertexShader(float z = 0.0f) const;
|
||||
std::string GenerateUVQuadVertexShader() const;
|
||||
std::string GenerateFillFragmentShader() const;
|
||||
std::string GenerateFillFragmentShader(const GSVector4i fixed_color) const;
|
||||
std::string GenerateFillFragmentShader(const GSVector4 fixed_color) const;
|
||||
std::string GenerateCopyFragmentShader(bool offset = true) const;
|
||||
|
||||
std::string GenerateImGuiVertexShader() const;
|
||||
|
|
Loading…
Reference in New Issue