diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 1690c8e45..acc21078c 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -3563,6 +3563,12 @@ void CompilerGLSL::emit_resources() fixup_implicit_builtin_block_names(execution.model); break; + case ExecutionModelFragment: + if (options.fragment.emulate_alpha_test_func != Options::Always && + options.fragment.emulate_alpha_test_func != Options::Never) + statement("uniform float SPIRV_Cross_AlphaTestRef;"); + break; + default: break; } @@ -16613,6 +16619,28 @@ void CompilerGLSL::emit_fixup() if (options.vertex.flip_vert_y) statement("gl_Position.y = -gl_Position.y;"); } + else if (get_entry_point().model == ExecutionModelFragment) + { + if (options.fragment.emulate_alpha_test_func == Options::Never) + { + statement("discard;"); + } + else if (options.fragment.emulate_alpha_test_func != Options::Always) + { + auto *output_var = find_color_output_by_location(0); + if (output_var && this->get(output_var->basetype).vecsize >= 4) + { + // We check for test fail, so we use the opposite operator + static const char *ops[Options::Always] = { + "", ">=", "!=", ">", "<=", "==", "<", + }; + assert(options.fragment.emulate_alpha_test_func < Options::Always); + const char *op = ops[options.fragment.emulate_alpha_test_func]; + statement("if (", to_expression(output_var->self), ".a ", op, + " SPIRV_Cross_AlphaTestRef) discard;"); + } + } + } } void CompilerGLSL::flush_phi(BlockID from, BlockID to) diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index 8a0026323..b5c4e4ba0 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -164,6 +164,18 @@ class CompilerGLSL : public Compiler Highp }; + enum CompareFunc + { + Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always, + }; + struct VertexOptions { // "Vertex-like shader" here is any shader stage that can write BuiltInPosition. @@ -189,6 +201,9 @@ class CompilerGLSL : public Compiler // Add precision highp int in ES targets when emitting GLES source. Precision default_float_precision = Mediump; Precision default_int_precision = Highp; + + // If this is not Always, injects an alpha test for the output with location 0. + CompareFunc emulate_alpha_test_func = Always; } fragment; };