GS/HW: Tweak AF shader

This commit is contained in:
TheLastRar
2026-06-02 22:31:52 +01:00
committed by lightningterror
parent 3f8eb5adf0
commit 9650c4b79a
5 changed files with 170 additions and 176 deletions
+45 -46
View File
@@ -361,23 +361,28 @@ bool2 nan_or_inf(float2 xy)
float4 sample_c_af(float2 uv, float uv_w)
{
// HW sampler will reject bad UVs, match that here.
uv = any(nan_or_inf(uv)) ? float2(0, 0) : uv;
uv = any(nan_or_inf(uv)) ? float2(0.0f, 0.0f) : uv;
// Large floating point values risk NaN/Inf values.
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
uv = clamp(uv, -8388608.0f, 8388608.0f);
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
// And https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_filter_anisotropic.txt
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
float2 sz;
Texture.GetDimensions(sz.x, sz.y);
float2 dX = ddx(uv) * sz;
float2 dY = ddy(uv) * sz;
float length_x = length(dX);
float length_y = length(dY);
// Calculate Ellipse Transform
bool d_zero = length(dX) == 0 || length(dY) == 0;
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
bool d_per = dot(dX, dY) == 0;
bool d_zero = length_x < 0.001f || length_y < 0.001f;
float f = (dX.x * dY.y - dX.y * dY.x);
bool d_par = f < 0.001f;
bool d_per = dot(dX, dY) < 0.001f;
bool d_inf_nan = any(nan_or_inf(dX) | nan_or_inf(dY));
if (!(d_zero || d_par || d_per || d_inf_nan))
@@ -385,42 +390,49 @@ float4 sample_c_af(float2 uv, float uv_w)
float A = dX.y * dX.y + dY.y * dY.y;
float B = -2 * (dX.x * dX.y + dY.x * dY.y);
float C = dX.x * dX.x + dY.x * dY.x;
float f = (dX.x * dY.y - dY.x * dX.y);
float F = f * f;
float p = A - C;
float q = A + C;
float t = sqrt(p * p + B * B);
float sqrt_num_plus = sqrt(F * (t + p));
float sqrt_num_minus = sqrt(F * (t - p));
float inv_sqrt_denom_plus = rsqrt(t * (q + t));
float inv_sqrt_denom_minus = rsqrt(t * (q - t));
float signB = sign(B);
float2 new_dX = float2(
sqrt(F * (t + p) / (t * (q + t))),
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
sqrt_num_plus * inv_sqrt_denom_plus,
sqrt_num_minus * inv_sqrt_denom_plus * signB
);
float2 new_dY = float2(
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
sqrt(F * (t + p) / (t * (q - t)))
sqrt_num_minus * inv_sqrt_denom_minus * -signB,
sqrt_num_plus * inv_sqrt_denom_minus
);
d_inf_nan = any(nan_or_inf(new_dX) | nan_or_inf(new_dY));
if (!d_inf_nan)
{
dX = new_dX;
dY = new_dY;
length_x = length(dX);
length_y = length(dY);
}
}
// Compute AF values
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
bool is_major_x = squared_length_x > squared_length_y;
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
float length_major = sqrt(squared_length_major);
bool is_major_x = length_x > length_y;
float length_major = is_major_x ? length_x : length_y;
float length_minor = is_major_x ? length_y : length_x;
float aniso_ratio;
float length_lod;
float2 aniso_line;
if (length_major <= 1.0f)
{
// A zero length_major would result in NaN Lod and break sampling.
@@ -428,57 +440,44 @@ float4 sample_c_af(float2 uv, float uv_w)
// Perform isotropic filtering instead.
aniso_ratio = 1.0f;
length_lod = length_major;
aniso_line = float2(0, 0);
aniso_line = float2(0.0f, 0.0f);
}
else
{
float norm_major = 1.0f / length_major;
float2 aniso_line_dir = float2(
(is_major_x ? dX.x : dY.x) * norm_major,
(is_major_x ? dX.y : dY.y) * norm_major
);
aniso_ratio = squared_length_major / determinant;
float2 aniso_line_dir = is_major_x ? dX : dY;
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
{
// ratio is clamped - Lod is based on ratio (preserves area)
aniso_ratio = PS_ANISOTROPIC_FILTERING;
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
}
else
{
// ratio not clamped - Lod is based on area
length_lod = determinant / length_major;
}
aniso_ratio = min(length_major / length_minor, PS_ANISOTROPIC_FILTERING);
length_lod = length_major / aniso_ratio;
// clamp to top Lod
if (length_lod < 1.0f)
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
aniso_ratio = round(aniso_ratio);
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
aniso_line = aniso_line_dir * 0.5f * (1.0f / sz);
}
#if PS_AUTOMATIC_LOD == 1
float lod = log2(length_lod);
#elif PS_MANUAL_LOD == 1
float lod = manual_lod(uv_w);
#else
float lod = 0; // No Lod
float lod = 0.0f; // No Lod
#endif
float4 colour;
if (aniso_ratio == 1.0f)
colour = Texture.SampleLevel(TextureSampler, uv, lod);
else
{
float4 num = float4(0, 0, 0, 0);
for (int i = 0; i < aniso_ratio; i++)
{
float2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
float4 num = float4(0.0f, 0.0f, 0.0f, 0.0f);
float2 segment = (2.0f * aniso_line) / aniso_ratio;
int aniso_ratio_i = (int)aniso_ratio;
for (int i = 0; i < aniso_ratio_i; i++)
{
float2 d = -aniso_line + (0.5f + i) * segment;
float2 uv_sample = uv + d;
float4 sample_colour = Texture.SampleLevel(TextureSampler, uv_sample, lod);
num += sample_colour;
+43 -45
View File
@@ -220,22 +220,27 @@ float manual_lod(float uv_w)
vec4 sample_c_af(vec2 uv, float uv_w)
{
// HW sampler will reject bad UVs, match that here.
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0, 0) : uv;
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0.0f, 0.0f) : uv;
// Large floating point values risk NaN/Inf values.
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
uv = clamp(uv, -8388608.0f, 8388608.0f);
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
// And https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_filter_anisotropic.txt
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
vec2 sz = textureSize(TextureSampler, 0);
vec2 dX = dFdx(uv) * sz;
vec2 dY = dFdy(uv) * sz;
float length_x = length(dX);
float length_y = length(dY);
// Calculate Ellipse Transform
bool d_zero = length(dX) == 0 || length(dY) == 0;
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
bool d_per = dot(dX, dY) == 0;
bool d_zero = length_x < 0.001f || length_y < 0.001f;
float f = (dX.x * dY.y - dX.y * dY.x);
bool d_par = f < 0.001f;
bool d_per = dot(dX, dY) < 0.001f;
bool d_inf_nan = any(isinf(dX)) || any(isinf(dY)) || any(isnan(dX)) || any(isnan(dY));
if (!(d_zero || d_par || d_per || d_inf_nan))
@@ -243,38 +248,46 @@ vec4 sample_c_af(vec2 uv, float uv_w)
float A = dX.y * dX.y + dY.y * dY.y;
float B = -2 * (dX.x * dX.y + dY.x * dY.y);
float C = dX.x * dX.x + dY.x * dY.x;
float f = (dX.x * dY.y - dY.x * dX.y);
float F = f * f;
float p = A - C;
float q = A + C;
float t = sqrt(p * p + B * B);
float signB = sign(B);
float denom_plus = t * (q + t);
float denom_minus = t * (q - t);
float sqrtA = sqrt(F * (t + p));
float sqrtB = sqrt(F * (t - p));
float inv_sqrt_denom_plus = inversesqrt(denom_plus);
float inv_sqrt_denom_minus = inversesqrt(denom_minus);
vec2 new_dX = vec2(
sqrt(F * (t + p) / (t * (q + t))),
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
sqrtA * inv_sqrt_denom_plus,
sqrtB * inv_sqrt_denom_plus * signB
);
vec2 new_dY = vec2(
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
sqrt(F * (t + p) / (t * (q - t)))
sqrtB * inv_sqrt_denom_minus * -signB,
sqrtA * inv_sqrt_denom_minus
);
d_inf_nan = any(isinf(new_dX)) || any(isinf(new_dY)) || any(isnan(new_dX)) || any(isnan(new_dY));
if (!d_inf_nan)
{
dX = new_dX;
dY = new_dY;
length_x = length(dX);
length_y = length(dY);
}
}
// Compute AF values
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
bool is_major_x = squared_length_x > squared_length_y;
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
float length_major = sqrt(squared_length_major);
bool is_major_x = length_x > length_y;
float length_major = is_major_x ? length_x : length_y;
float length_minor = is_major_x ? length_y : length_x;
float aniso_ratio;
float length_lod;
@@ -286,57 +299,42 @@ vec4 sample_c_af(vec2 uv, float uv_w)
// Perform isotropic filtering instead.
aniso_ratio = 1.0f;
length_lod = length_major;
aniso_line = vec2(0, 0);
aniso_line = vec2(0.0f, 0.0f);
}
else
{
float norm_major = 1.0f / length_major;
vec2 aniso_line_dir = vec2(
(is_major_x ? dX.x : dY.x) * norm_major,
(is_major_x ? dX.y : dY.y) * norm_major
);
aniso_ratio = squared_length_major / determinant;
vec2 aniso_line_dir = is_major_x ? dX : dY;
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
{
// ratio is clamped - Lod is based on ratio (preserves area)
aniso_ratio = PS_ANISOTROPIC_FILTERING;
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
}
else
{
// ratio not clamped - Lod is based on area
length_lod = determinant / length_major;
}
aniso_ratio = min(length_major / length_minor, PS_ANISOTROPIC_FILTERING);
length_lod = length_major / aniso_ratio;
// clamp to top Lod
if (length_lod < 1.0f)
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
aniso_ratio = round(aniso_ratio);
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
aniso_line = aniso_line_dir * 0.5f * (1.0f / sz);
}
#if PS_AUTOMATIC_LOD == 1
float lod = log2(length_lod);
#elif PS_MANUAL_LOD == 1
float lod = manual_lod(uv_w);
#else
float lod = 0; // No Lod
float lod = 0.0f; // No Lod
#endif
vec4 colour;
if (aniso_ratio == 1.0f)
colour = textureLod(TextureSampler, uv, lod);
else
{
vec4 num = vec4(0, 0, 0, 0);
vec4 num = vec4(0.0f, 0.0f, 0.0f, 0.0f);
vec2 segment = (2.0f * aniso_line) / aniso_ratio;
for (int i = 0; i < aniso_ratio; i++)
{
vec2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
{
vec2 d = -aniso_line + (0.5f + i) * segment;
vec2 uv_sample = uv + d;
vec4 sample_colour = textureLod(TextureSampler, uv_sample, lod);
num += sample_colour;
+43 -44
View File
@@ -728,22 +728,27 @@ float manual_lod(float uv_w)
vec4 sample_c_af(vec2 uv, float uv_w)
{
// HW sampler will reject bad UVs, match that here.
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0, 0) : uv;
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0.0f, 0.0f) : uv;
// Large floating point values risk NaN/Inf values.
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
uv = clamp(uv, -8388608.0f, 8388608.0f);
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
// And https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_filter_anisotropic.txt
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
vec2 sz = textureSize(Texture, 0);
vec2 dX = dFdx(uv) * sz;
vec2 dY = dFdy(uv) * sz;
float length_x = length(dX);
float length_y = length(dY);
// Calculate Ellipse Transform
bool d_zero = length(dX) == 0 || length(dY) == 0;
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
bool d_per = dot(dX, dY) == 0;
bool d_zero = length_x < 0.001f || length_y < 0.001f;
float f = (dX.x * dY.y - dX.y * dY.x);
bool d_par = f < 0.001f;
bool d_per = dot(dX, dY) < 0.001f;
bool d_inf_nan = any(isinf(dX)) || any(isinf(dY)) || any(isnan(dX)) || any(isnan(dY));
if (!(d_zero || d_par || d_per || d_inf_nan))
@@ -758,31 +763,40 @@ vec4 sample_c_af(vec2 uv, float uv_w)
float q = A + C;
float t = sqrt(p * p + B * B);
float signB = sign(B);
float denom_plus = t * (q + t);
float denom_minus = t * (q - t);
float sqrtA = sqrt(F * (t + p));
float sqrtB = sqrt(F * (t - p));
float inv_sqrt_denom_plus = inversesqrt(denom_plus);
float inv_sqrt_denom_minus = inversesqrt(denom_minus);
vec2 new_dX = vec2(
sqrt(F * (t + p) / (t * (q + t))),
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
sqrtA * inv_sqrt_denom_plus,
sqrtB * inv_sqrt_denom_plus * signB
);
vec2 new_dY = vec2(
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
sqrt(F * (t + p) / (t * (q - t)))
sqrtB * inv_sqrt_denom_minus * -signB,
sqrtA * inv_sqrt_denom_minus
);
d_inf_nan = any(isinf(new_dX)) || any(isinf(new_dY)) || any(isnan(new_dX)) || any(isnan(new_dY));
if (!d_inf_nan)
{
dX = new_dX;
dY = new_dY;
length_x = length(dX);
length_y = length(dY);
}
}
// Compute AF values
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
bool is_major_x = squared_length_x > squared_length_y;
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
float length_major = sqrt(squared_length_major);
bool is_major_x = length_x > length_y;
float length_major = is_major_x ? length_x : length_y;
float length_minor = is_major_x ? length_y : length_x;
float aniso_ratio;
float length_lod;
@@ -794,57 +808,42 @@ vec4 sample_c_af(vec2 uv, float uv_w)
// Perform isotropic filtering instead.
aniso_ratio = 1.0f;
length_lod = length_major;
aniso_line = vec2(0, 0);
aniso_line = vec2(0.0f, 0.0f);
}
else
{
float norm_major = 1.0f / length_major;
vec2 aniso_line_dir = vec2(
(is_major_x ? dX.x : dY.x) * norm_major,
(is_major_x ? dX.y : dY.y) * norm_major
);
aniso_ratio = squared_length_major / determinant;
vec2 aniso_line_dir = is_major_x ? dX : dY;
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
{
// ratio is clamped - Lod is based on ratio (preserves area)
aniso_ratio = PS_ANISOTROPIC_FILTERING;
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
}
else
{
// ratio not clamped - Lod is based on area
length_lod = determinant / length_major;
}
aniso_ratio = min(length_major / length_minor, PS_ANISOTROPIC_FILTERING);
length_lod = length_major / aniso_ratio;
// clamp to top Lod
if (length_lod < 1.0f)
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
aniso_ratio = round(aniso_ratio);
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
aniso_line = aniso_line_dir * 0.5f * (1.0f / sz);
}
#if PS_AUTOMATIC_LOD == 1
float lod = log2(length_lod);
#elif PS_MANUAL_LOD == 1
float lod = manual_lod(uv_w);
#else
float lod = 0; // No Lod
float lod = 0.0f; // No Lod
#endif
vec4 colour;
if (aniso_ratio == 1.0f)
colour = textureLod(Texture, uv, lod);
else
{
vec4 num = vec4(0, 0, 0, 0);
vec4 num = vec4(0.0f, 0.0f, 0.0f, 0.0f);
vec2 segment = (2.0f * aniso_line) / aniso_ratio;
for (int i = 0; i < aniso_ratio; i++)
{
vec2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
{
vec2 d = -aniso_line + (0.5f + i) * segment;
vec2 uv_sample = uv + d;
vec4 sample_colour = textureLod(Texture, uv_sample, lod);
num += sample_colour;
+38 -40
View File
@@ -611,22 +611,27 @@ struct PSMain
float4 sample_c_af(float2 uv, float uv_w)
{
// HW sampler will reject bad UVs, match that here.
uv = any(isnan(uv) | isinf(uv)) ? float2(0, 0) : uv;
uv = any(isnan(uv) | isinf(uv)) ? float2(0.0f, 0.0f) : uv;
// Large floating point values risk NaN/Inf values.
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
uv = clamp(uv, -8388608.0f, 8388608.0f);
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
// And https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_filter_anisotropic.txt
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
float2 sz = float2(get_tex_dims());
float2 dX = dfdx(uv) * sz;
float2 dY = dfdy(uv) * sz;
float length_x = length(dX);
float length_y = length(dY);
// Calculate Ellipse Transform
bool d_zero = length(dX) == 0 || length(dY) == 0;
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
bool d_per = dot(dX, dY) == 0;
bool d_zero = length_x < 0.001f || length_y < 0.001f;
float f = (dX.x * dY.y - dX.y * dY.x);
bool d_par = f < 0.001f;
bool d_per = dot(dX, dY) < 0.001f;
bool d_inf_nan = any(isinf(dX) | isinf(dY) | isnan(dX) | isnan(dY));
if (!(d_zero || d_par || d_per || d_inf_nan))
@@ -634,21 +639,30 @@ struct PSMain
float A = dX.y * dX.y + dY.y * dY.y;
float B = -2 * (dX.x * dX.y + dY.x * dY.y);
float C = dX.x * dX.x + dY.x * dY.x;
float f = (dX.x * dY.y - dY.x * dX.y);
float F = f * f;
float p = A - C;
float q = A + C;
float t = sqrt(p * p + B * B);
float signB = sign(B);
float denom_plus = t * (q + t);
float denom_minus = t * (q - t);
float sqrtA = sqrt(F * (t + p));
float sqrtB = sqrt(F * (t - p));
float inv_sqrt_denom_plus = rsqrt(denom_plus);
float inv_sqrt_denom_minus = rsqrt(denom_minus);
float2 new_dX = float2(
sqrt(F * (t + p) / (t * (q + t))),
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
sqrtA * inv_sqrt_denom_plus,
sqrtB * inv_sqrt_denom_plus * signB
);
float2 new_dY = float2(
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
sqrt(F * (t + p) / (t * (q - t)))
sqrtB * inv_sqrt_denom_minus * -signB,
sqrtA * inv_sqrt_denom_minus
);
d_inf_nan = any(isinf(new_dX) | isinf(new_dY) | isnan(new_dX) | isnan(new_dY));
@@ -656,16 +670,15 @@ struct PSMain
{
dX = new_dX;
dY = new_dY;
length_x = length(dX);
length_y = length(dY);
}
}
// Compute AF values
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
bool is_major_x = squared_length_x > squared_length_y;
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
float length_major = sqrt(squared_length_major);
bool is_major_x = length_x > length_y;
float length_major = is_major_x ? length_x : length_y;
float length_minor = is_major_x ? length_y : length_x;
float aniso_ratio;
float length_lod;
@@ -677,41 +690,25 @@ struct PSMain
// Perform isotropic filtering instead.
aniso_ratio = 1.0f;
length_lod = length_major;
aniso_line = float2(0, 0);
aniso_line = float2(0.0f, 0.0f);
}
else
{
float norm_major = 1.0f / length_major;
float2 aniso_line_dir = is_major_x ? dX : dY;
float2 aniso_line_dir = float2(
(is_major_x ? dX.x : dY.x) * norm_major,
(is_major_x ? dX.y : dY.y) * norm_major
);
aniso_ratio = squared_length_major / determinant;
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
if (aniso_ratio > PS_SW_ANISO)
{
// ratio is clamped - Lod is based on ratio (preserves area)
aniso_ratio = PS_SW_ANISO;
length_lod = length_major / PS_SW_ANISO;
}
else
{
// ratio not clamped - Lod is based on area
length_lod = determinant / length_major;
}
aniso_ratio = min(length_major / length_minor, float(PS_SW_ANISO));
length_lod = length_major / aniso_ratio;
// clamp to top Lod
if (length_lod < 1.0f)
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
aniso_ratio = round(aniso_ratio);
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
aniso_line = aniso_line_dir * 0.5f * (1.0f / sz);
}
float lod = PS_AUTOMATIC_LOD ? log2(length_lod) : PS_MANUAL_LOD ? manual_lod(uv_w) : 0;
float lod = PS_AUTOMATIC_LOD ? log2(length_lod) : PS_MANUAL_LOD ? manual_lod(uv_w) : 0.0f;
float4 colour;
if (aniso_ratio == 1.0f)
@@ -720,10 +717,11 @@ struct PSMain
}
else
{
float4 num = float4(0, 0, 0, 0);
float4 num = float4(0.0f, 0.0f, 0.0f, 0.0f);
float2 segment = (2.0f * aniso_line) / aniso_ratio;
for (int i = 0; i < aniso_ratio; i++)
{
float2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
float2 d = -aniso_line + (0.5f + i) * segment;
float2 uv_sample = uv + d;
float4 sample_colour = sample_tex(tex_sampler, uv_sample, level(lod));
num += sample_colour;
+1 -1
View File
@@ -3,4 +3,4 @@
/// Version number for GS and other shaders. Increment whenever any of the contents of the
/// shaders change, to invalidate the cache.
static constexpr u32 SHADER_CACHE_VERSION = 104; // Last changed in PR 14603
static constexpr u32 SHADER_CACHE_VERSION = 105; // Last changed in PR 14465