Added premult alpha blending to 3D (spatial) shaders.

Co-authored-by: jitspoe <jitspoe@yahoo.com>
Co-authored-by: Clay John <claynjohn@gmail.com>
This commit is contained in:
QbieShay 2023-12-01 15:57:29 +01:00
parent d282e4f0e6
commit 41a2b0e83e
14 changed files with 76 additions and 6 deletions

View File

@ -609,6 +609,9 @@
<constant name="BLEND_MODE_MUL" value="3" enum="BlendMode"> <constant name="BLEND_MODE_MUL" value="3" enum="BlendMode">
The color of the object is multiplied by the background. The color of the object is multiplied by the background.
</constant> </constant>
<constant name="BLEND_MODE_PREMULT_ALPHA" value="4" enum="BlendMode">
The color of the object is added to the background and the alpha channel is used to mask out the background. This is effectively a hybrid of the blend mix and add modes, useful for FX like fire where you want the flame to add but the smoke to mix. By default, this works with unshaded materials using premultiplied textures. For shaded materials, use the PREMUL_ALPHA_FACTOR built-in so that lighting can be modulated as well.
</constant>
<constant name="ALPHA_ANTIALIASING_OFF" value="0" enum="AlphaAntiAliasing"> <constant name="ALPHA_ANTIALIASING_OFF" value="0" enum="AlphaAntiAliasing">
Disables Alpha AntiAliasing for the material. Disables Alpha AntiAliasing for the material.
</constant> </constant>

View File

@ -3040,6 +3040,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE); glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
} }
} break;
case GLES3::SceneShaderData::BLEND_MODE_PREMULT_ALPHA: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} break; } break;
case GLES3::SceneShaderData::BLEND_MODE_ALPHA_TO_COVERAGE: { case GLES3::SceneShaderData::BLEND_MODE_ALPHA_TO_COVERAGE: {
// Do nothing for now. // Do nothing for now.

View File

@ -1442,6 +1442,9 @@ void main() {
float clearcoat_roughness = 0.0; float clearcoat_roughness = 0.0;
float anisotropy = 0.0; float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0); vec2 anisotropy_flow = vec2(1.0, 0.0);
#ifdef PREMULT_ALPHA_USED
float premult_alpha = 1.0;
#endif
#ifndef FOG_DISABLED #ifndef FOG_DISABLED
vec4 fog = vec4(0.0); vec4 fog = vec4(0.0);
#endif // !FOG_DISABLED #endif // !FOG_DISABLED
@ -2141,9 +2144,12 @@ void main() {
frag_color.rgb += additive_light_color; frag_color.rgb += additive_light_color;
#endif // USE_ADDITIVE_LIGHTING #endif // USE_ADDITIVE_LIGHTING
frag_color.rgb *= scene_data.luminance_multiplier; frag_color.rgb *= scene_data.luminance_multiplier;
#endif // !RENDER_MATERIAL #endif // !RENDER_MATERIAL
#endif // !MODE_RENDER_DEPTH #endif // !MODE_RENDER_DEPTH
#ifdef PREMULT_ALPHA_USED
frag_color.rgb *= premult_alpha;
#endif
} }

View File

@ -1243,6 +1243,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["ALBEDO"] = "albedo"; actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha"; actions.renames["ALPHA"] = "alpha";
actions.renames["PREMULT_ALPHA_FACTOR"] = "premult_alpha";
actions.renames["METALLIC"] = "metallic"; actions.renames["METALLIC"] = "metallic";
actions.renames["SPECULAR"] = "specular"; actions.renames["SPECULAR"] = "specular";
actions.renames["ROUGHNESS"] = "roughness"; actions.renames["ROUGHNESS"] = "roughness";
@ -1327,6 +1328,7 @@ MaterialStorage::MaterialStorage() {
actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n"; actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n"; actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n";
actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE"; actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE";
actions.usage_defines["PREMULT_ALPHA_FACTOR"] = "#define PREMULT_ALPHA_USED";
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
@ -2908,6 +2910,7 @@ void SceneShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX); actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX);
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB); actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB);
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL); actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL);
actions.render_mode_values["blend_premult_alpha"] = Pair<int *, int>(&blend_modei, BLEND_MODE_PREMULT_ALPHA);
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE); actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);

View File

@ -248,6 +248,7 @@ struct SceneShaderData : public ShaderData {
BLEND_MODE_ADD, BLEND_MODE_ADD,
BLEND_MODE_SUB, BLEND_MODE_SUB,
BLEND_MODE_MUL, BLEND_MODE_MUL,
BLEND_MODE_PREMULT_ALPHA,
BLEND_MODE_ALPHA_TO_COVERAGE BLEND_MODE_ALPHA_TO_COVERAGE
}; };

View File

@ -688,6 +688,9 @@ void BaseMaterial3D::_update_shader() {
case BLEND_MODE_MUL: case BLEND_MODE_MUL:
code += "blend_mul"; code += "blend_mul";
break; break;
case BLEND_MODE_PREMULT_ALPHA:
code += "blend_premul_alpha";
break;
case BLEND_MODE_MAX: case BLEND_MODE_MAX:
break; // Internal value, skip. break; // Internal value, skip.
} }
@ -1819,6 +1822,11 @@ void fragment() {)";
vec3 detail = mix(ALBEDO.rgb, ALBEDO.rgb * detail_tex.rgb, detail_tex.a); vec3 detail = mix(ALBEDO.rgb, ALBEDO.rgb * detail_tex.rgb, detail_tex.a);
)"; )";
} break; } break;
case BLEND_MODE_PREMULT_ALPHA: {
// This is unlikely to ever be used for detail textures, and in order for it to function in the editor, another bit must be used in MaterialKey,
// but there are only 5 bits left, so I'm going to leave this disabled unless it's actually requested.
//code += "\tvec3 detail = (1.0-detail_tex.a)*ALBEDO.rgb+detail_tex.rgb;\n";
} break;
case BLEND_MODE_MAX: case BLEND_MODE_MAX:
break; // Internal value, skip. break; // Internal value, skip.
} }
@ -3040,7 +3048,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing"); ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge");
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply"), "set_blend_mode", "get_blend_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply,Premultiplied Alpha"), "set_blend_mode", "get_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never"), "set_depth_draw_mode", "get_depth_draw_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never"), "set_depth_draw_mode", "get_depth_draw_mode");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST);
@ -3269,6 +3277,7 @@ void BaseMaterial3D::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_MODE_ADD); BIND_ENUM_CONSTANT(BLEND_MODE_ADD);
BIND_ENUM_CONSTANT(BLEND_MODE_SUB); BIND_ENUM_CONSTANT(BLEND_MODE_SUB);
BIND_ENUM_CONSTANT(BLEND_MODE_MUL); BIND_ENUM_CONSTANT(BLEND_MODE_MUL);
BIND_ENUM_CONSTANT(BLEND_MODE_PREMULT_ALPHA);
BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_OFF); BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_OFF);
BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);

View File

@ -219,6 +219,7 @@ public:
BLEND_MODE_ADD, BLEND_MODE_ADD,
BLEND_MODE_SUB, BLEND_MODE_SUB,
BLEND_MODE_MUL, BLEND_MODE_MUL,
BLEND_MODE_PREMULT_ALPHA,
BLEND_MODE_MAX BLEND_MODE_MAX
}; };

View File

@ -90,6 +90,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX); actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB); actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL); actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
actions.render_mode_values["blend_premult_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULT_ALPHA);
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE); actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
@ -244,7 +245,17 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
} } break;
case BLEND_MODE_PREMULT_ALPHA: {
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
uses_blend_alpha = true; // Force alpha used because of blend.
} break;
} }
// Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular, attachment 2: Motion Vectors // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular, attachment 2: Motion Vectors
@ -593,6 +604,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["ALBEDO"] = "albedo"; actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha"; actions.renames["ALPHA"] = "alpha";
actions.renames["PREMULT_ALPHA_FACTOR"] = "premult_alpha";
actions.renames["METALLIC"] = "metallic"; actions.renames["METALLIC"] = "metallic";
actions.renames["SPECULAR"] = "specular"; actions.renames["SPECULAR"] = "specular";
actions.renames["ROUGHNESS"] = "roughness"; actions.renames["ROUGHNESS"] = "roughness";
@ -672,6 +684,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
actions.usage_defines["LIGHT_VERTEX"] = "#define LIGHT_VERTEX_USED\n"; actions.usage_defines["LIGHT_VERTEX"] = "#define LIGHT_VERTEX_USED\n";
actions.usage_defines["PREMULT_ALPHA_FACTOR"] = "#define PREMULT_ALPHA_USED\n";
actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n"; actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n";
actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n"; actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";

View File

@ -106,7 +106,8 @@ public:
BLEND_MODE_ADD, BLEND_MODE_ADD,
BLEND_MODE_SUB, BLEND_MODE_SUB,
BLEND_MODE_MUL, BLEND_MODE_MUL,
BLEND_MODE_ALPHA_TO_COVERAGE BLEND_MODE_ALPHA_TO_COVERAGE,
BLEND_MODE_PREMULT_ALPHA,
}; };
enum DepthDraw { enum DepthDraw {

View File

@ -91,6 +91,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX); actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB); actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL); actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
actions.render_mode_values["blend_premult_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULT_ALPHA);
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE); actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
@ -255,7 +256,17 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
} } break;
case BLEND_MODE_PREMULT_ALPHA: {
blend_attachment.enable_blend = true;
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
uses_blend_alpha = true; // Force alpha used because of blend.
} break;
} }
RD::PipelineColorBlendState blend_state_blend; RD::PipelineColorBlendState blend_state_blend;
@ -497,6 +508,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["ALBEDO"] = "albedo"; actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha"; actions.renames["ALPHA"] = "alpha";
actions.renames["PREMULT_ALPHA_FACTOR"] = "premult_alpha";
actions.renames["METALLIC"] = "metallic"; actions.renames["METALLIC"] = "metallic";
actions.renames["SPECULAR"] = "specular"; actions.renames["SPECULAR"] = "specular";
actions.renames["ROUGHNESS"] = "roughness"; actions.renames["ROUGHNESS"] = "roughness";
@ -581,6 +593,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n"; actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n"; actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n";
actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE"; actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE";
actions.usage_defines["PREMULT_ALPHA_FACTOR"] = "#define PREMULT_ALPHA_USED";
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";

View File

@ -61,6 +61,7 @@ public:
BLEND_MODE_ADD, BLEND_MODE_ADD,
BLEND_MODE_SUB, BLEND_MODE_SUB,
BLEND_MODE_MUL, BLEND_MODE_MUL,
BLEND_MODE_PREMULT_ALPHA,
BLEND_MODE_ALPHA_TO_COVERAGE BLEND_MODE_ALPHA_TO_COVERAGE
}; };

View File

@ -914,6 +914,9 @@ vec3 encode24(vec3 v) {
void fragment_shader(in SceneData scene_data) { void fragment_shader(in SceneData scene_data) {
uint instance_index = instance_index_interp; uint instance_index = instance_index_interp;
#ifdef PREMULT_ALPHA_USED
float premult_alpha = 1.0;
#endif // PREMULT_ALPHA_USED
//lay out everything, whatever is unused is optimized away anyway //lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp; vec3 vertex = vertex_interp;
#ifdef USE_MULTIVIEW #ifdef USE_MULTIVIEW
@ -2458,6 +2461,10 @@ void fragment_shader(in SceneData scene_data) {
motion_vector = prev_position_uv - position_uv; motion_vector = prev_position_uv - position_uv;
#endif #endif
#if defined(PREMULT_ALPHA_USED) && !defined(MODE_RENDER_DEPTH)
frag_color.rgb *= premult_alpha;
#endif //PREMULT_ALPHA_USED
} }
void main() { void main() {

View File

@ -749,6 +749,9 @@ void main() {
float clearcoat_roughness = 0.0; float clearcoat_roughness = 0.0;
float anisotropy = 0.0; float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0); vec2 anisotropy_flow = vec2(1.0, 0.0);
#ifdef PREMULT_ALPHA_USED
float premult_alpha = 1.0;
#endif
#ifndef FOG_DISABLED #ifndef FOG_DISABLED
vec4 fog = vec4(0.0); vec4 fog = vec4(0.0);
#endif // !FOG_DISABLED #endif // !FOG_DISABLED
@ -1846,6 +1849,9 @@ void main() {
// On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking // On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking
// We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images // We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images
frag_color.rgb = frag_color.rgb / sc_luminance_multiplier; frag_color.rgb = frag_color.rgb / sc_luminance_multiplier;
#ifdef PREMULT_ALPHA_USED
frag_color.rgb *= premult_alpha;
#endif
#endif //MODE_MULTIPLE_RENDER_TARGETS #endif //MODE_MULTIPLE_RENDER_TARGETS

View File

@ -124,6 +124,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["PREMULT_ALPHA_FACTOR"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SPECULAR"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SPECULAR"] = ShaderLanguage::TYPE_FLOAT;
@ -208,7 +209,7 @@ ShaderTypes::ShaderTypes() {
// spatial render modes // spatial render modes
{ {
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("blend"), "mix", "add", "sub", "mul" }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("blend"), "mix", "add", "sub", "mul", "premult_alpha" });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_draw"), "opaque", "always", "never" }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_draw"), "opaque", "always", "never" });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_prepass_alpha") }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_prepass_alpha") });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test_disabled") }); shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test_disabled") });