diff --git a/bin/resources/shaders/dx11/tfx.fx b/bin/resources/shaders/dx11/tfx.fx index 04eb4b3f7b..644bec937a 100644 --- a/bin/resources/shaders/dx11/tfx.fx +++ b/bin/resources/shaders/dx11/tfx.fx @@ -976,8 +976,10 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy) } else if (PS_BLEND_HW == 4) { - // Needed for Cd * (1 - Ad) - Color.rgb = (float3)128.0f; + // Needed for Cd * (1 - Ad) and Cd*(1 + Alpha) + float Alpha = PS_BLEND_C == 2 ? Af : As; + As_rgba.rgb = (float3)Alpha * (float3)(128.0f / 255.0f); + Color.rgb = (float3)127.5f; } } } diff --git a/bin/resources/shaders/opengl/tfx_fs.glsl b/bin/resources/shaders/opengl/tfx_fs.glsl index a502a7faa7..28e65b632c 100644 --- a/bin/resources/shaders/opengl/tfx_fs.glsl +++ b/bin/resources/shaders/opengl/tfx_fs.glsl @@ -936,8 +936,15 @@ float As = As_rgba.a; float color_compensate = 255.0f / max(128.0f, max_color); Color.rgb *= vec3(color_compensate); #elif PS_BLEND_HW == 4 - // Needed for Cd * (1 - Ad) - Color.rgb = vec3(128.0f); + // Needed for Cd * (1 - Ad) and Cd*(1 + Alpha) + +#if PS_BLEND_C == 2 + float Alpha = Af; +#else + float Alpha = As; +#endif + As_rgba.rgb = vec3(Alpha) * vec3(128.0f / 255.0f); + Color.rgb = vec3(127.5f); #endif #endif diff --git a/bin/resources/shaders/vulkan/tfx.glsl b/bin/resources/shaders/vulkan/tfx.glsl index ab109e4a5e..40efb1cea7 100644 --- a/bin/resources/shaders/vulkan/tfx.glsl +++ b/bin/resources/shaders/vulkan/tfx.glsl @@ -1203,8 +1203,16 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba) float color_compensate = 255.0f / max(128.0f, max_color); Color.rgb *= vec3(color_compensate); #elif PS_BLEND_HW == 4 - // Needed for Cd * (1 - Ad) - Color.rgb = vec3(128.0f); + // Needed for Cd * (1 - Ad) and Cd*(1 + Alpha) + + #if PS_BLEND_C == 2 + float Alpha = Af; + #else + float Alpha = As; + #endif + + As_rgba.rgb = vec3(Alpha) * vec3(128.0f / 255.0f); + Color.rgb = vec3(127.5f); #endif #endif } diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index b0e7d0b09e..bc1226d9aa 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -4496,6 +4496,18 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT m_conf.blend_second_pass.blend_hw = 2; m_conf.blend_second_pass.blend = {true, GSDevice::DST_COLOR, (m_conf.ps.blend_c == 2) ? GSDevice::CONST_COLOR : GSDevice::SRC1_COLOR, GSDevice::OP_ADD, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, m_conf.ps.blend_c == 2, AFIX}; } + else if ((alpha_c0_high_max_one || alpha_c1_high_no_rta_correct || alpha_c2_high_one) && (blend_flag & BLEND_HW1)) + { + // Alpha = As, Ad or Af. + // Cd*(1 + Alpha). + // Render pass 1: Do Cd*(1 + Alpha) with a half result in the end. + m_conf.ps.blend_hw = 4; + blend.dst = (m_conf.ps.blend_c == 1) ? GSDevice::DST_ALPHA : GSDevice::SRC1_COLOR; + // Render pass 2: Take result (Cd) from render pass 1 and double it. + m_conf.blend_second_pass.enable = true; + m_conf.blend_second_pass.blend_hw = 1; + m_conf.blend_second_pass.blend = {true, blend_second_pass.src, GSDevice::CONST_ONE, blend_second_pass.op, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0}; + } else if (alpha_c1_high_no_rta_correct && (blend_flag & BLEND_HW3)) { // Alpha = Ad. @@ -4580,7 +4592,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT } } - if (blend_flag & BLEND_HW1) + if (!m_conf.blend_second_pass.enable && blend_flag & BLEND_HW1) { m_conf.ps.blend_hw = 1; } @@ -4593,7 +4605,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT m_conf.ps.blend_hw = 3; } - if (m_conf.ps.blend_c == 2 && (m_conf.ps.blend_hw == 2 || m_conf.blend_second_pass.blend_hw == 2)) + if (m_conf.ps.blend_c == 2 && (m_conf.ps.blend_hw == 2 || m_conf.ps.blend_hw == 4 || m_conf.blend_second_pass.blend_hw == 2)) m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast(AFIX) / 128.0f; const GSDevice::BlendFactor src_factor_alpha = m_conf.blend_second_pass.enable ? GSDevice::CONST_ZERO : GSDevice::CONST_ONE;