GS-hw: Further improve how we handle blend mix 1.

Compensate slightly for Cd*(As + 1) - Cs*As.
Try to compensate a bit with substracting 1 (0.00392) * (Alpha + 1) from Cs.
The initial factor we chose is 1 (0.00392) as that is the minimum color Cd can be, then we multiply by alpha to get the minimum blended value it can be.
This commit is contained in:
lightningterror 2022-08-09 09:56:00 +02:00
parent 8fbb1e5565
commit abcbdc4a25
5 changed files with 58 additions and 12 deletions

View File

@ -778,8 +778,9 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
// As/Af clamp alpha for Blend mix
// We shouldn't clamp blend mix with clr1 as we want alpha higher
float C_clamped = C;
if (PS_BLEND_MIX > 0 && PS_CLR_HW != 1)
C = min(C, 1.0f);
C_clamped = min(C_clamped, 1.0f);
if (PS_BLEND_A == PS_BLEND_B)
Color.rgb = D;
@ -791,9 +792,9 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
// Based on the scripts at the above link, the ideal choice for Intel GPUs is 126/256, AMD 120/256. Nvidia is a lost cause.
// 124/256 seems like a reasonable compromise, providing the correct answer 99.3% of the time on Intel (vs 99.6% for 126/256), and 97% of the time on AMD (vs 97.4% for 120/256).
else if (PS_BLEND_MIX == 2)
Color.rgb = ((A - B) * C + D) + (124.0f/256.0f);
Color.rgb = ((A - B) * C_clamped + D) + (124.0f / 256.0f);
else if (PS_BLEND_MIX == 1)
Color.rgb = ((A - B) * C + D) - (124.0f/256.0f);
Color.rgb = ((A - B) * C_clamped + D) - (124.0f / 256.0f);
else
Color.rgb = trunc(((A - B) * C) + D);
@ -811,6 +812,16 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
float alpha_compensate = max(1.0f, min_color / 255.0f);
As -= alpha_compensate;
}
else if (PS_CLR_HW == 2)
{
// Compensate slightly for Cd*(As + 1) - Cs*As.
// The initial factor we chose is 1 (0.00392)
// as that is the minimum color Cd can be,
// then we multiply by alpha to get the minimum
// blended value it can be.
float color_compensate = 1.0f * (C + 1.0f);
Color.rgb -= (float3)color_compensate;
}
}
else
{

View File

@ -721,8 +721,9 @@ void ps_blend(inout vec4 Color, inout float As)
// As/Af clamp alpha for Blend mix
// We shouldn't clamp blend mix with clr1 as we want alpha higher
float C_clamped = C;
#if PS_BLEND_MIX > 0 && PS_CLR_HW != 1
C = min(C, 1.0f);
C_clamped = min(C_clamped, 1.0f);
#endif
#if PS_BLEND_A == PS_BLEND_B
@ -735,9 +736,9 @@ void ps_blend(inout vec4 Color, inout float As)
// Based on the scripts at the above link, the ideal choice for Intel GPUs is 126/256, AMD 120/256. Nvidia is a lost cause.
// 124/256 seems like a reasonable compromise, providing the correct answer 99.3% of the time on Intel (vs 99.6% for 126/256), and 97% of the time on AMD (vs 97.4% for 120/256).
#elif PS_BLEND_MIX == 2
Color.rgb = ((A - B) * C + D) + (124.0f/256.0f);
Color.rgb = ((A - B) * C_clamped + D) + (124.0f/256.0f);
#elif PS_BLEND_MIX == 1
Color.rgb = ((A - B) * C + D) - (124.0f/256.0f);
Color.rgb = ((A - B) * C_clamped + D) - (124.0f/256.0f);
#else
Color.rgb = trunc((A - B) * C + D);
#endif
@ -755,6 +756,14 @@ void ps_blend(inout vec4 Color, inout float As)
float min_color = min(min(Color.r, Color.g), Color.b);
float alpha_compensate = max(1.0f, min_color / 255.0f);
As -= alpha_compensate;
#elif PS_CLR_HW == 2
// Compensate slightly for Cd*(As + 1) - Cs*As.
// The initial factor we chose is 1 (0.00392)
// as that is the minimum color Cd can be,
// then we multiply by alpha to get the minimum
// blended value it can be.
float color_compensate = 1.0f * (C + 1.0f);
Color.rgb -= vec3(color_compensate);
#endif
#else

View File

@ -1053,8 +1053,9 @@ void ps_blend(inout vec4 Color, inout float As)
// As/Af clamp alpha for Blend mix
// We shouldn't clamp blend mix with clr1 as we want alpha higher
float C_clamped = C;
#if PS_BLEND_MIX > 0 && PS_CLR_HW != 1
C = min(C, 1.0f);
C_clamped = min(C_clamped, 1.0f);
#endif
#if PS_BLEND_A == PS_BLEND_B
@ -1067,9 +1068,9 @@ void ps_blend(inout vec4 Color, inout float As)
// Based on the scripts at the above link, the ideal choice for Intel GPUs is 126/256, AMD 120/256. Nvidia is a lost cause.
// 124/256 seems like a reasonable compromise, providing the correct answer 99.3% of the time on Intel (vs 99.6% for 126/256), and 97% of the time on AMD (vs 97.4% for 120/256).
#elif PS_BLEND_MIX == 2
Color.rgb = ((A - B) * C + D) + (124.0f/256.0f);
Color.rgb = ((A - B) * C_clamped + D) + (124.0f/256.0f);
#elif PS_BLEND_MIX == 1
Color.rgb = ((A - B) * C + D) - (124.0f/256.0f);
Color.rgb = ((A - B) * C_clamped + D) - (124.0f/256.0f);
#else
Color.rgb = trunc((A - B) * C + D);
#endif
@ -1087,6 +1088,14 @@ void ps_blend(inout vec4 Color, inout float As)
float min_color = min(min(Color.r, Color.g), Color.b);
float alpha_compensate = max(1.0f, min_color / 255.0f);
As -= alpha_compensate;
#elif PS_CLR_HW == 2
// Compensate slightly for Cd*(As + 1) - Cs*As.
// The initial factor we chose is 1 (0.00392)
// as that is the minimum color Cd can be,
// then we multiply by alpha to get the minimum
// blended value it can be.
float color_compensate = 1.0f * (C + 1.0f);
Color.rgb -= vec3(color_compensate);
#endif
#else

View File

@ -2914,6 +2914,12 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
// DSB output will always be used.
m_conf.ps.no_color1 = false;
}
else if (m_conf.ps.blend_a == m_conf.ps.blend_d)
{
// Compensate slightly for Cd*(As + 1) - Cs*As.
// Try to compensate a bit with subtracting 1 (0.00392) * (Alpha + 1) from Cs.
m_conf.ps.clr_hw = 2;
}
m_conf.ps.blend_a = 0;
m_conf.ps.blend_b = 2;

View File

@ -835,8 +835,9 @@ struct PSMain
// As/Af clamp alpha for Blend mix
// We shouldn't clamp blend mix with clr1 as we want alpha higher
float C_clamped = C;
if (PS_BLEND_MIX > 0 && PS_CLR_HW != 1)
C = min(C, 1.f);
C_clamped = min(C_clamped, 1.f);
if (PS_BLEND_A == PS_BLEND_B)
Color.rgb = D;
@ -848,9 +849,9 @@ struct PSMain
// Based on the scripts at the above link, the ideal choice for Intel GPUs is 126/256, AMD 120/256. Nvidia is a lost cause.
// 124/256 seems like a reasonable compromise, providing the correct answer 99.3% of the time on Intel (vs 99.6% for 126/256), and 97% of the time on AMD (vs 97.4% for 120/256).
else if (PS_BLEND_MIX == 2)
Color.rgb = ((A - B) * C + D) + (124.f/256.f);
Color.rgb = ((A - B) * C_clamped + D) + (124.f/256.f);
else if (PS_BLEND_MIX == 1)
Color.rgb = ((A - B) * C + D) - (124.f/256.f);
Color.rgb = ((A - B) * C_clamped + D) - (124.f/256.f);
else
Color.rgb = trunc((A - B) * C + D);
@ -868,6 +869,16 @@ struct PSMain
float alpha_compensate = max(1.f, min_color / 255.f);
As -= alpha_compensate;
}
else if (PS_CLR_HW == 2)
{
// Compensate slightly for Cd*(As + 1) - Cs*As.
// The initial factor we chose is 1 (0.00392)
// as that is the minimum color Cd can be,
// then we multiply by alpha to get the minimum
// blended value it can be.
float color_compensate = 1.f * (C + 1.f);
Color.rgb -= float3(color_compensate);
}
}
else
{