From aecc73e89337c8cc73054285a660d6cefd8c91b9 Mon Sep 17 00:00:00 2001 From: jerrrrycho Date: Sun, 8 Nov 2026 01:34:35 +0100 Subject: [PATCH] fix(render): antialias alpha tested edges with multisampling (eu07/maszyna#449) The sides of the trackbed (and grass, fences, foliage) are cut out of their textures by the alpha test, which keeps or drops whole pixels, so their edges stayed jagged at any multisampling level; only geometry edges got smoothed. With multisampling on, the alpha tested materials of the opaque colour pass now draw with GL_SAMPLE_ALPHA_TO_COVERAGE. Their shaders do the alpha test with alpha_test_fail() of glsl_common and write as alpha the coverage of the test edge: the alpha sharpened around the opacity threshold to go from 0 to 1 over about a pixel, so the edge keeps the place it had and gets the samples it covers. The renderer turns alpha to coverage on per material, only for shaders which use the helper and only in the opaque pass with a positive opacity, so translucent, water, terrain and the other shaders are unchanged. Without multisampling the shaders work as before. --- ci_shadervalidator/Globals.h | 1 + gl/glsl_common.cpp | 30 +++++++++++++++++++ gl/shader.cpp | 3 ++ gl/shader.h | 4 +++ rendering/opengl33renderer.cpp | 24 +++++++++++++++ rendering/opengl33renderer.h | 3 ++ shaders/mat_default.frag | 5 ++-- shaders/mat_default_detail.frag | 5 ++-- shaders/mat_default_specgloss.frag | 5 ++-- shaders/mat_detail_normalmap.frag | 5 ++-- shaders/mat_detail_normalmap_specgloss.frag | 5 ++-- shaders/mat_detail_parallax.frag | 5 ++-- shaders/mat_detail_parallax_specgloss.frag | 5 ++-- shaders/mat_normalmap.frag | 5 ++-- shaders/mat_normalmap_specgloss.frag | 5 ++-- shaders/mat_parallax.frag | 5 ++-- shaders/mat_parallax_specgloss.frag | 5 ++-- shaders/mat_reflmap.frag | 5 ++-- shaders/mat_reflmap_specgloss.frag | 5 ++-- shaders/mat_shadowlessnormalmap.frag | 5 ++-- .../mat_shadowlessnormalmap_specgloss.frag | 5 ++-- shaders/mat_sunlessnormalmap.frag | 5 ++-- shaders/mat_sunlessnormalmap_specgloss.frag | 5 ++-- 23 files changed, 116 insertions(+), 34 deletions(-) diff --git a/ci_shadervalidator/Globals.h b/ci_shadervalidator/Globals.h index 16f85e80..e8f548dc 100644 --- a/ci_shadervalidator/Globals.h +++ b/ci_shadervalidator/Globals.h @@ -8,6 +8,7 @@ struct _global bool gfx_extraeffects; bool gfx_shadergamma; bool gfx_usegles; + int iMultisampling; }; extern _global Global; diff --git a/gl/glsl_common.cpp b/gl/glsl_common.cpp index 26c31000..a0d38de6 100644 --- a/gl/glsl_common.cpp +++ b/gl/glsl_common.cpp @@ -11,6 +11,7 @@ void gl::glsl_common_setup() "#define MOTIONBLUR_ENABLED " + std::to_string((int)Global.gfx_postfx_motionblur_enabled) + "\n" + "#define POSTFX_ENABLED " + std::to_string((int)!Global.gfx_skippipeline) + "\n" + "#define EXTRAEFFECTS_ENABLED " + std::to_string((int)Global.gfx_extraeffects) + "\n" + + "#define ALPHA_TO_COVERAGE_ENABLED " + std::to_string((int)(Global.iMultisampling > 0)) + "\n" + "#define MAX_LIGHTS " + std::to_string(MAX_LIGHTS) + "U\n" + "#define MAX_CASCADES " + std::to_string(MAX_CASCADES) + "U\n" + "#define MAX_PARAMS " + std::to_string(MAX_PARAMS) + "U\n" + @@ -110,5 +111,34 @@ void gl::glsl_common_setup() } #endif + #ifdef STAGE_FRAGMENT + // alpha tested surfaces (positive opacity, the opaque pass) get the coverage of their alpha + // test edge from GL_SAMPLE_ALPHA_TO_COVERAGE, which the renderer turns on for them with + // multisampling; otherwise the alpha test keeps or drops whole pixels and its edges stay + // jagged whatever the multisampling. the alpha is sharpened to go from 0 to 1 over about + // a pixel around the test threshold, so the edge keeps the place and sharpness the alpha + // test gave it. computed before any discard, which leaves the derivatives undefined + float alpha_coverage(float alpha) + { + #if ALPHA_TO_COVERAGE_ENABLED + if (opacity > 0.0) + return clamp((alpha - opacity) / max(fwidth(alpha), 0.0001) + 0.5, 0.0, 1.0); + #endif + return alpha; + } + + // true for the fragments the alpha test drops: below the opacity threshold in the opaque + // pass, at or above it (negative opacity) in the translucent pass. with alpha to coverage + // only the fragments which cover no sample at all + bool alpha_test_fail(float alpha, float coverage) + { + #if ALPHA_TO_COVERAGE_ENABLED + if (opacity > 0.0) + return coverage <= 0.0; + #endif + return (opacity >= 0.0 ? (alpha < opacity) : (alpha >= -opacity)); + } + #endif + )STRING"; } diff --git a/gl/shader.cpp b/gl/shader.cpp index 9160a2c9..31a3e6a8 100644 --- a/gl/shader.cpp +++ b/gl/shader.cpp @@ -175,6 +175,8 @@ std::pair gl::shader::process_source(const std::string &fil str += "vec4 FBOUT(vec4 x) { return " + (Global.gfx_shadergamma ? std::string("vec4(pow(x.rgb, vec3(1.0 / 2.2)), x.a)") : std::string("x")) + "; }\n"; str += read_file(basedir + filename); + // checked before the includes are expanded, since glsl_common defines the function + alpha_to_coverage = ( str.find( "alpha_test_fail(" ) != std::string::npos ); expand_includes(str, basedir); parse_texture_entries(str); @@ -381,6 +383,7 @@ void gl::program::attach(const gl::shader &s) texture_conf.try_emplace(texturename, std::move(textureentry)); for (auto [paramname, paramentry] : s.param_conf) param_conf.try_emplace(paramname, std::move(paramentry)); + alpha_to_coverage = alpha_to_coverage || s.alpha_to_coverage; glAttachShader(*this, *s); } diff --git a/gl/shader.h b/gl/shader.h index f1735a0e..e46c1427 100644 --- a/gl/shader.h +++ b/gl/shader.h @@ -63,6 +63,9 @@ namespace gl std::unordered_map texture_conf; std::unordered_map param_conf; std::string name; + // the shader does its alpha test with alpha_test_fail() of glsl_common, so its alpha + // output can drive GL_SAMPLE_ALPHA_TO_COVERAGE in the opaque pass + bool alpha_to_coverage{ false }; #ifndef SHADERVALIDATOR_STANDALONE private: @@ -96,6 +99,7 @@ namespace gl std::unordered_map texture_conf; std::unordered_map param_conf; + bool alpha_to_coverage{ false }; private: void init(); diff --git a/rendering/opengl33renderer.cpp b/rendering/opengl33renderer.cpp index 932ac31f..d577312b 100644 --- a/rendering/opengl33renderer.cpp +++ b/rendering/opengl33renderer.cpp @@ -1820,6 +1820,18 @@ void opengl33_renderer::setup_matrices() OpenGLMatrices.load_matrix(glm::mat4{glm::mat3{m_renderpass.pass_camera.modelview()}}); } +void opengl33_renderer::setup_alpha_to_coverage(bool const Enable) +{ + if (Enable == m_alphatocoverageenabled) + return; + + if (Enable) + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); + else + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + m_alphatocoverageenabled = Enable; +} + void opengl33_renderer::setup_drawing(bool const Alpha) { if (Alpha) @@ -1834,6 +1846,8 @@ void opengl33_renderer::setup_drawing(bool const Alpha) glDepthMask(GL_TRUE); m_blendingenabled = false; } + // turned on again per material, by the ones which need it + setup_alpha_to_coverage(false); switch (m_renderpass.draw_mode) { @@ -2374,6 +2388,16 @@ void opengl33_renderer::Bind_Material( material_handle const Material, TSubModel else model_ubs.alpha_mult = 1.0f; + // the alpha test drops or keeps whole pixels, so multisampling alone leaves its edges (e.g. sides + // of the trackbed textures) jagged. the alpha tested materials of the opaque colour pass get them + // antialiased with alpha to coverage instead; their shaders give the coverage as the alpha + setup_alpha_to_coverage( + Global.iMultisampling > 0 + && false == m_blendingenabled + && m_renderpass.draw_mode == rendermode::color + && model_ubs.opacity > 0.f + && material.shader->alpha_to_coverage ); + // materials which declare texture variants provide a different texture set per model instance, // picked from the seed of the rendered instance and the variant group of the submodel auto const &materialtextures{ diff --git a/rendering/opengl33renderer.h b/rendering/opengl33renderer.h index 1b489738..0e84761e 100644 --- a/rendering/opengl33renderer.h +++ b/rendering/opengl33renderer.h @@ -277,6 +277,8 @@ class opengl33_renderer : public gfx_renderer { void setup_pass(viewport_config &Viewport, renderpass_config &Config, rendermode const Mode, float const Znear = 0.f, float const Zfar = 1.f, bool const Ignoredebug = false); void setup_matrices(); void setup_drawing(bool const Alpha = false); + // alpha to coverage for the alpha tested materials of the opaque colour pass, when multisampled + void setup_alpha_to_coverage(bool const Enable); void setup_shadow_unbind_map(); void setup_shadow_bind_map(); void setup_shadow_color( glm::vec4 const &Shadowcolor ); @@ -560,6 +562,7 @@ class opengl33_renderer : public gfx_renderer { material_handle m_invalid_material; bool m_blendingenabled; + bool m_alphatocoverageenabled{ false }; bool m_widelines_supported; diff --git a/shaders/mat_default.frag b/shaders/mat_default.frag index bc48d939..5459f1d2 100644 --- a/shaders/mat_default.frag +++ b/shaders/mat_default.frag @@ -29,7 +29,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -42,7 +43,7 @@ void main() glossiness = abs(param[1].w); fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, 0.0, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); /* float distance = dot(f_pos.xyz, f_pos.xyz); if( distance <= cascade_end.x ) { color.r += 0.25; } diff --git a/shaders/mat_default_detail.frag b/shaders/mat_default_detail.frag index 63d15c7c..0f8ad7d5 100644 --- a/shaders/mat_default_detail.frag +++ b/shaders/mat_default_detail.frag @@ -35,7 +35,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -52,7 +53,7 @@ void main() glossiness = abs(param[1].w); fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_default_specgloss.frag b/shaders/mat_default_specgloss.frag index 254a0cc7..52d94aec 100644 --- a/shaders/mat_default_specgloss.frag +++ b/shaders/mat_default_specgloss.frag @@ -32,7 +32,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -46,7 +47,7 @@ void main() metalic = texture(specgloss, f_coord).b; fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); /* float distance = dot(f_pos.xyz, f_pos.xyz); if( distance <= cascade_end.x ) { color.r += 0.25; } diff --git a/shaders/mat_detail_normalmap.frag b/shaders/mat_detail_normalmap.frag index 85f55289..debfe3ba 100644 --- a/shaders/mat_detail_normalmap.frag +++ b/shaders/mat_detail_normalmap.frag @@ -39,7 +39,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; @@ -64,7 +65,7 @@ void main() float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5; fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_detail_normalmap_specgloss.frag b/shaders/mat_detail_normalmap_specgloss.frag index a3799ce1..0fa9ea2e 100644 --- a/shaders/mat_detail_normalmap_specgloss.frag +++ b/shaders/mat_detail_normalmap_specgloss.frag @@ -42,7 +42,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -72,7 +73,7 @@ void main() fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_detail_parallax.frag b/shaders/mat_detail_parallax.frag index 75919b13..28de2509 100644 --- a/shaders/mat_detail_parallax.frag +++ b/shaders/mat_detail_parallax.frag @@ -49,7 +49,8 @@ void main() vec4 detailnormal_map = texture(detailnormalmap, f_coord_p * param[2].x); vec4 tex_color = texture(diffuse, f_coord_p); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -72,7 +73,7 @@ void main() fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_detail_parallax_specgloss.frag b/shaders/mat_detail_parallax_specgloss.frag index fcc33ac3..8d1b8645 100644 --- a/shaders/mat_detail_parallax_specgloss.frag +++ b/shaders/mat_detail_parallax_specgloss.frag @@ -55,7 +55,8 @@ void main() vec4 tex_color = texture(diffuse, f_coord_p); vec4 specgloss_map = texture(specgloss, f_coord_p); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; @@ -78,7 +79,7 @@ void main() fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_normalmap.frag b/shaders/mat_normalmap.frag index 3ef505eb..9757324d 100644 --- a/shaders/mat_normalmap.frag +++ b/shaders/mat_normalmap.frag @@ -34,7 +34,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -51,7 +52,7 @@ void main() fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_normalmap_specgloss.frag b/shaders/mat_normalmap_specgloss.frag index a4b18462..3f043b51 100644 --- a/shaders/mat_normalmap_specgloss.frag +++ b/shaders/mat_normalmap_specgloss.frag @@ -38,7 +38,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -57,7 +58,7 @@ void main() fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_parallax.frag b/shaders/mat_parallax.frag index 7adac054..49e8eb2a 100644 --- a/shaders/mat_parallax.frag +++ b/shaders/mat_parallax.frag @@ -42,7 +42,8 @@ void main() vec4 tex_color = texture(diffuse, f_coord_p); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -59,7 +60,7 @@ void main() fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_parallax_specgloss.frag b/shaders/mat_parallax_specgloss.frag index 8b590fae..04349ef2 100644 --- a/shaders/mat_parallax_specgloss.frag +++ b/shaders/mat_parallax_specgloss.frag @@ -46,7 +46,8 @@ void main() vec4 tex_color = texture(diffuse, f_coord_p); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -65,7 +66,7 @@ void main() fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_reflmap.frag b/shaders/mat_reflmap.frag index bd4c4ae7..1ffdd822 100644 --- a/shaders/mat_reflmap.frag +++ b/shaders/mat_reflmap.frag @@ -32,7 +32,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -49,7 +50,7 @@ void main() if(alphatestfail) fragcolor.r = 1.0; - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; diff --git a/shaders/mat_reflmap_specgloss.frag b/shaders/mat_reflmap_specgloss.frag index 4c89083c..71ebbac2 100644 --- a/shaders/mat_reflmap_specgloss.frag +++ b/shaders/mat_reflmap_specgloss.frag @@ -36,7 +36,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -54,7 +55,7 @@ void main() if(alphatestfail) fragcolor.r = 1.0; - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; diff --git a/shaders/mat_shadowlessnormalmap.frag b/shaders/mat_shadowlessnormalmap.frag index cb2c040e..ebf135ba 100644 --- a/shaders/mat_shadowlessnormalmap.frag +++ b/shaders/mat_shadowlessnormalmap.frag @@ -34,7 +34,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -51,7 +52,7 @@ void main() glossiness = abs(param[1].w); fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, 1.0); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_shadowlessnormalmap_specgloss.frag b/shaders/mat_shadowlessnormalmap_specgloss.frag index adc473ff..2bd6d215 100644 --- a/shaders/mat_shadowlessnormalmap_specgloss.frag +++ b/shaders/mat_shadowlessnormalmap_specgloss.frag @@ -38,7 +38,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -56,7 +57,7 @@ void main() metalic = texture(specgloss, f_coord).b; fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, 1.0); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_sunlessnormalmap.frag b/shaders/mat_sunlessnormalmap.frag index 0b3fc7f6..a5e97d30 100644 --- a/shaders/mat_sunlessnormalmap.frag +++ b/shaders/mat_sunlessnormalmap.frag @@ -99,7 +99,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -115,7 +116,7 @@ void main() float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5; fragcolor = apply_lights_sunless(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else diff --git a/shaders/mat_sunlessnormalmap_specgloss.frag b/shaders/mat_sunlessnormalmap_specgloss.frag index 21cc9f6e..4e2abe1d 100644 --- a/shaders/mat_sunlessnormalmap_specgloss.frag +++ b/shaders/mat_sunlessnormalmap_specgloss.frag @@ -113,7 +113,8 @@ void main() { vec4 tex_color = texture(diffuse, f_coord); - bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) ); + float alphacoverage = alpha_coverage(tex_color.a); + bool alphatestfail = alpha_test_fail(tex_color.a, alphacoverage); if(alphatestfail) discard; // if (tex_color.a < opacity) @@ -131,7 +132,7 @@ void main() metalic = texture(specgloss, f_coord).b; fragcolor = apply_lights_sunless(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone); - vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult); + vec4 color = vec4(apply_fog(fragcolor), alphacoverage * alpha_mult); #if POSTFX_ENABLED out_color = color; #else