]> git.tdb.fi Git - libs/gl.git/commitdiff
Add support for alpha to coverage
authorMikko Rasa <tdb@tdb.fi>
Sat, 23 Apr 2022 16:33:58 +0000 (19:33 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 23 Apr 2022 21:33:00 +0000 (00:33 +0300)
shaderlib/common.glsl
shaderlib/cooktorrance.glsl
shaderlib/phong.glsl
shaderlib/unlit.glsl
source/backends/opengl/pipelinestate_backend.cpp
source/backends/vulkan/pipelinestate_backend.cpp
source/core/blend.cpp
source/core/blend.h
source/materials/material.cpp
source/materials/material.h

index 300726dc541c0f7d4cfcdfdcdba9094f4662f242..695bce3b5da4ca0d8b06c5785a8bcea6f2c1da3a 100644 (file)
@@ -1,10 +1,17 @@
 import msp_interface;
 import shadow;
 
+struct AlphaCutoffParams
+{
+       float cutoff;
+       float feather;
+};
+
 layout(set=1) uniform sampler2D normal_map;
 
 layout(constant_id=auto) const bool use_instancing = false;
 layout(constant_id=auto) const bool use_normal_map = false;
+layout(constant_id=auto) const bool use_alpha_cutoff = false;
 
 #pragma MSP stage(vertex)
 virtual vec4 get_vertex_position()
@@ -95,6 +102,19 @@ virtual IncomingLight get_incoming_light(int index, vec3 world_pos)
        return IncomingLight(rel_pos/d, light_sources[index].color*attenuation);
 }
 
+float apply_alpha_cutoff(float alpha, AlphaCutoffParams params)
+{
+       if(use_alpha_cutoff)
+       {
+               if(alpha<params.cutoff)
+                       discard;
+               float limit = min(params.cutoff+params.feather*fwidth(alpha), 1.0);
+               return smoothstep(params.cutoff, limit, alpha);
+       }
+       else
+               return alpha;
+}
+
 vec3 apply_fog(vec3 color)
 {
        float fog_value = exp(fog_coord*fog_density);
index e942b49ebab2bb5cb9e5553b004e5e112b36fe5e..1c564a04557a39b3b0ab951b8c2b86acb7f4b32e 100644 (file)
@@ -14,7 +14,7 @@ struct PbrMaterialParameters
 layout(set=1) uniform PbrMaterial
 {
        PbrMaterialParameters pbr_material;
-       float alpha_cutoff;
+       AlphaCutoffParams alpha_cutoff;
 };
 
 layout(set=1) uniform sampler2D base_color_map;
@@ -31,7 +31,6 @@ layout(constant_id=auto) const bool use_occlusion_map = false;
 layout(constant_id=auto) const bool use_emission = false;
 layout(constant_id=auto) const bool use_emission_map = false;
 layout(constant_id=auto) const bool use_image_based_lighting = false;
-layout(constant_id=auto) const bool use_alpha_cutoff = false;
 
 #pragma MSP stage(fragment)
 virtual vec4 get_base_color()
@@ -177,8 +176,7 @@ vec3 cooktorrance_lighting(vec3 normal, vec3 look, vec3 base_color, float metaln
 void main()
 {
        vec4 base_color = get_base_color();
-       if(use_alpha_cutoff && base_color.a<alpha_cutoff)
-               discard;
+       float alpha = apply_alpha_cutoff(base_color.a, alpha_cutoff);
 
        vec3 normal = get_fragment_normal();
        vec3 look = normalize(world_look_dir);
@@ -188,5 +186,5 @@ void main()
 
        vec3 lit_color = cooktorrance_lighting(normal, look, base_color.rgb, metalness, roughness);
 
-       frag_color = vec4(lit_color, base_color.a);
+       frag_color = vec4(lit_color, alpha);
 }
index 28e9e5007be0af9c7e706353d2a67c16ea965ab2..5334455cd240cf1cba32084852ad33b3a673f1f2 100644 (file)
@@ -14,7 +14,7 @@ struct BasicMaterialParameters
 layout(set=1) uniform BasicMaterial
 {
        BasicMaterialParameters basic_material;
-       float alpha_cutoff;
+       AlphaCutoffParameters alpha_cutoff;
 };
 
 layout(set=1) uniform sampler2D diffuse_map;
@@ -31,7 +31,6 @@ layout(constant_id=auto) const bool use_emission = false;
 layout(constant_id=auto) const bool use_emission_map = false;
 layout(constant_id=auto) const bool use_reflectivity = false;
 layout(constant_id=auto) const bool use_reflectivity_map = false;
-layout(constant_id=auto) const bool use_alpha_cutoff = false;
 
 #pragma MSP stage(fragment)
 virtual vec4 get_diffuse_color()
@@ -115,8 +114,7 @@ vec3 phong_lighting(vec3 normal, vec3 look, vec3 surface_diffuse, vec3 surface_s
 void main()
 {
        vec4 surface_diffuse = get_diffuse_color();
-       if(use_alpha_cutoff && surface_diffuse.a<alpha_cutoff)
-               discard;
+       float alpha = apply_alpha_cutoff(surface_diffuse.a, alpha_cutoff);
 
        vec3 normal = get_fragment_normal();
        vec3 look = normalize(world_look_dir);
@@ -126,5 +124,5 @@ void main()
 
        vec3 lit_color = phong_lighting(normal, look, surface_diffuse.rgb, surface_specular, shininess);
 
-       frag_color = vec4(lit_color, surface_diffuse.a);
+       frag_color = vec4(lit_color, alpha);
 }
index 29cfd3f2cf0257874b40c0a0901e5ca9157bb9da..a7d75c3248a59150e9cd70fa749ce05df975eb16 100644 (file)
@@ -9,7 +9,7 @@ struct UnlitMaterialParameters
 layout(set=1) uniform UnlitMaterial
 {
        UnlitMaterialParameters unlit_material;
-       float alpha_cutoff;
+       AlphaCutoffParams alpha_cutoff;
 };
 
 layout(set=1) uniform sampler2D color_tex;
@@ -17,7 +17,6 @@ layout(set=1) uniform sampler2D color_tex;
 layout(constant_id=auto) const bool use_texture = false;
 layout(constant_id=auto) const bool use_vertex_color = false;
 layout(constant_id=auto) const bool use_fog = false;
-layout(constant_id=auto) const bool use_alpha_cutoff = false;
 
 #pragma MSP stage(fragment)
 virtual vec4 get_color()
@@ -33,8 +32,7 @@ virtual vec4 get_color()
 void main()
 {
        vec4 color = get_color();
-       if(use_alpha_cutoff && color.a<alpha_cutoff)
-               discard;
+       color.a = apply_alpha_cutoff(color.a, alpha_cutoff);
 
        if(use_fog)
                color.rgb = apply_fog(color.rgb);
index a2b8ab32717555bc329b85a515f2b58818738ff0..8ffa47fcda75d8ea44e9ff9e74673ca54f43a21a 100644 (file)
@@ -237,6 +237,11 @@ void OpenGLPipelineState::apply() const
                        glDisable(GL_BLEND);
                        glColorMask(true, true, true, true);
                }
+
+               if(blend.alpha_to_coverage && self.framebuffer && self.framebuffer->get_format().get_samples()>1)
+                       glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+               else
+                       glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
        }
 
        applied_to = &device;
index 1578f9976d61452b200fd0066bb02f16ca4074e5..9c695b3d1a5d281abda8ccc0d8a2df4b1e60b775 100644 (file)
@@ -118,6 +118,8 @@ uint64_t VulkanPipelineState::compute_hash() const
                }
 
                result = hash_round<64>(result, format.get_samples());
+               if(format.get_samples()>1)
+                       result = hash_round<64>(result, self.blend.alpha_to_coverage);
 
                if(self.depth_test.enabled)
                {
@@ -216,7 +218,7 @@ void VulkanPipelineState::fill_graphics_creation_info(vector<char> &buffer) cons
        multisample_info->sampleShadingEnable = VK_FALSE;
        multisample_info->minSampleShading = 1.0f;
        multisample_info->pSampleMask = 0;
-       multisample_info->alphaToCoverageEnable = VK_FALSE;
+       multisample_info->alphaToCoverageEnable = (format.get_samples()>1 && self.blend.alpha_to_coverage ? VK_TRUE : VK_FALSE);
        multisample_info->alphaToOneEnable = VK_FALSE;
 
        depth_stencil_info->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
index 99ffcd075c933a4441a8535dfed14b735a09acb4..2923cb452217351a9a2f3da1f685ed29dc0cd053 100644 (file)
@@ -24,6 +24,7 @@ Blend::Blend(BlendEquation e, BlendFactor sf, BlendFactor df):
 Blend::Loader::Loader(Blend &b):
        ObjectLoader<Blend>(b)
 {
+       add("alpha_to_coverage", &Blend::alpha_to_coverage);
        add("equation", &Loader::equation);
        add("factors", &Loader::factors);
        add("constant", &Loader::constant);
index 3edebc8c7f4bdde90e8d7aa14c2ab87cc300ff04..874230c682c9ccf82e21c88a644f1dc61aa6034d 100644 (file)
@@ -67,6 +67,7 @@ struct Blend
        BlendFactor dst_factor = ZERO;
        Color constant = { 0.0f, 0.0f, 0.0f, 0.0f };
        ColorWriteMask write_mask = WRITE_ALL;
+       bool alpha_to_coverage = false;
 
        Blend() = default;
        Blend(BlendFactor, BlendFactor);
@@ -79,7 +80,8 @@ struct Blend
 inline bool Blend::operator==(const Blend &other) const
 {
        return enabled==other.enabled && equation==other.equation && src_factor==other.src_factor &&
-               dst_factor==other.dst_factor && constant==other.constant && write_mask==other.write_mask;
+               dst_factor==other.dst_factor && constant==other.constant && write_mask==other.write_mask &&
+               alpha_to_coverage==other.alpha_to_coverage;
 }
 
 
index 6af833e6b5c30e48badcfd6bec78d45bce64eeee..542c84744b2f2b4dbb2c0fa434c240ee0908999d 100644 (file)
@@ -14,6 +14,7 @@ namespace GL {
 Material::Material()
 {
        set_alpha_cutoff(0.0f);
+       set_alpha_feather(1.0f);
 }
 
 const Program *Material::create_compatible_shader(const map<string, int> &extra_spec) const
@@ -59,7 +60,13 @@ const Program *Material::create_compatible_shader(const map<string, int> &extra_
 void Material::set_alpha_cutoff(float a)
 {
        alpha_cutoff = a;
-       shdata.uniform("alpha_cutoff", a);
+       shdata.uniform("alpha_cutoff.cutoff", a);
+}
+
+void Material::set_alpha_feather(float f)
+{
+       alpha_feather = f;
+       shdata.uniform("alpha_cutoff.feather", f);
 }
 
 void Material::set_debug_name(const string &name)
@@ -93,6 +100,7 @@ Material::Loader::Loader(Material &m, Collection &c):
 void Material::Loader::init_actions()
 {
        add("alpha_cutoff", &Loader::alpha_cutoff);
+       add("alpha_cutoff", &Loader::alpha_cutoff_feather);
        add("sampler", &Loader::sampler);
 }
 
@@ -101,6 +109,12 @@ void Material::Loader::alpha_cutoff(float a)
        obj.set_alpha_cutoff(a);
 }
 
+void Material::Loader::alpha_cutoff_feather(float a, float f)
+{
+       obj.set_alpha_cutoff(a);
+       obj.set_alpha_feather(f);
+}
+
 void Material::Loader::sampler(const string &name)
 {
        obj.sampler = &get_collection().get<Sampler>(name);
index 75ff972cd4e1312de7e6d63a74480bf3c3b0409a..3210c96612fcfc2739d7fb99134f086c0c3761f9 100644 (file)
@@ -28,6 +28,7 @@ private:
 
        private:
                void alpha_cutoff(float);
+               void alpha_cutoff_feather(float, float);
                void sampler(const std::string &);
        };
 
@@ -74,6 +75,7 @@ public:
 protected:
        const Sampler *sampler = 0;
        float alpha_cutoff = 0.0f;
+       float alpha_feather = 1.0f;
        ProgramData shdata;
 
        Material();
@@ -98,8 +100,10 @@ public:
        virtual const Texture *get_texture(Tag) const = 0;
        virtual const Sampler *get_sampler(Tag) const { return sampler; }
 
-       void set_alpha_cutoff(float a);
+       void set_alpha_cutoff(float);
+       void set_alpha_feather(float);
        float get_alpha_cutoff() const { return alpha_cutoff; }
+       float get_alpha_feather() const { return alpha_feather; }
 
        void set_debug_name(const std::string &);