Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add premult alpha blending to 3D (spatial) shaders #85609

Merged
merged 1 commit into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/classes/BaseMaterial3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,9 @@
<constant name="BLEND_MODE_MUL" value="3" enum="BlendMode">
The color of the object is multiplied by the background.
</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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be [code]PREMULT_ALPHA_FACTOR[/code].

</constant>
<constant name="ALPHA_ANTIALIASING_OFF" value="0" enum="AlphaAntiAliasing">
Disables Alpha AntiAliasing for the material.
</constant>
Expand Down
5 changes: 5 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3040,6 +3040,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
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;
case GLES3::SceneShaderData::BLEND_MODE_ALPHA_TO_COVERAGE: {
// Do nothing for now.
Expand Down
8 changes: 7 additions & 1 deletion drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,9 @@ void main() {
float clearcoat_roughness = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
#ifdef PREMULT_ALPHA_USED
float premult_alpha = 1.0;
#endif
#ifndef FOG_DISABLED
vec4 fog = vec4(0.0);
#endif // !FOG_DISABLED
Expand Down Expand Up @@ -2141,9 +2144,12 @@ void main() {

frag_color.rgb += additive_light_color;
#endif // USE_ADDITIVE_LIGHTING

frag_color.rgb *= scene_data.luminance_multiplier;

#endif // !RENDER_MATERIAL
#endif // !MODE_RENDER_DEPTH

#ifdef PREMULT_ALPHA_USED
frag_color.rgb *= premult_alpha;
#endif
}
3 changes: 3 additions & 0 deletions drivers/gles3/storage/material_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha";
actions.renames["PREMULT_ALPHA_FACTOR"] = "premult_alpha";
actions.renames["METALLIC"] = "metallic";
actions.renames["SPECULAR"] = "specular";
actions.renames["ROUGHNESS"] = "roughness";
Expand Down Expand Up @@ -1327,6 +1328,7 @@ MaterialStorage::MaterialStorage() {
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_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_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
Expand Down Expand Up @@ -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_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_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_and_one"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/storage/material_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ struct SceneShaderData : public ShaderData {
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
BLEND_MODE_PREMULT_ALPHA,
BLEND_MODE_ALPHA_TO_COVERAGE
};

Expand Down
11 changes: 10 additions & 1 deletion scene/resources/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,9 @@ void BaseMaterial3D::_update_shader() {
case BLEND_MODE_MUL:
code += "blend_mul";
break;
case BLEND_MODE_PREMULT_ALPHA:
code += "blend_premul_alpha";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged a bit too fast, this one is still wrong.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it seems like we had this BLEND_MODE_PREMULT_ALPHA but blend_premul_alpha inconsistency in CanvasItem shaders already.

Should we fix it in Spatial shaders and accept that we have an inconsistency in 2D blend_premul_alpha / 3D blend_premult_alpha, or should we do like in 2D?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that too, but I'd rather not start touching things elsewhere for now

Copy link
Member

@akien-mga akien-mga May 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean this one is a bug, it's writing blend_premul_alpha in Spatial shaders but what's expected is blend_premult_alpha. I haven't tested but I think the latest update before merge broke the feature.

So we have two options:

  • Fix this one up to be blend_premult_alpha, and accept that 3D shaders will use a different keyword from 2D shaders
  • Go back to the previous version of your PR before my review (I didn't know you just replicated the inconsistency of existing 2D keywords) and use blend_premul_alpha in 3D too.

And yes to be clear we shouldn't change 2D shaders, that would break compat.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't remember either, and frankly I wonder if I did it on purpose or not. I'm not sure if we want to keep consistent with 2d and generally inconsistent, or if we should have correct 3d and weird 2D. Is there any precedent we can reference to take the decision?

break;
case BLEND_MODE_MAX:
break; // Internal value, skip.
}
Expand Down Expand Up @@ -1819,6 +1822,11 @@ void fragment() {)";
vec3 detail = mix(ALBEDO.rgb, ALBEDO.rgb * detail_tex.rgb, detail_tex.a);
)";
} 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";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@QbieShay I don't understand why this is commented out. Before the nuance is lost to the sands of time can you expand a little more? 5 bits left where?

uint64_t detail_blend_mode : get_num_bits(BLEND_MODE_MAX - 1);

The bits as far as I can tell are already spent allocating BLEND_MODE_PREMULT_ALPHA. Commenting it out just seems a little strange.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that was probably taken from my original PR which didn't have the bits taken. I was hesitant to waste a bit for this, but if the bit is already taken, this should be uncommented.

} break;
case BLEND_MODE_MAX:
break; // Internal value, skip.
}
Expand Down Expand Up @@ -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::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::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, "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);
Expand Down Expand Up @@ -3269,6 +3277,7 @@ void BaseMaterial3D::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_MODE_ADD);
BIND_ENUM_CONSTANT(BLEND_MODE_SUB);
BIND_ENUM_CONSTANT(BLEND_MODE_MUL);
BIND_ENUM_CONSTANT(BLEND_MODE_PREMULT_ALPHA);

BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_OFF);
BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
Expand Down
1 change: 1 addition & 0 deletions scene/resources/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class BaseMaterial3D : public Material {
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
BLEND_MODE_PREMULT_ALPHA,
BLEND_MODE_MAX
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_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_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
Expand Down Expand Up @@ -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.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
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
Expand Down Expand Up @@ -593,6 +604,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha";
actions.renames["PREMULT_ALPHA_FACTOR"] = "premult_alpha";
actions.renames["METALLIC"] = "metallic";
actions.renames["SPECULAR"] = "specular";
actions.renames["ROUGHNESS"] = "roughness";
Expand Down Expand Up @@ -672,6 +684,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\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_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ class SceneShaderForwardClustered {
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
BLEND_MODE_ALPHA_TO_COVERAGE
BLEND_MODE_ALPHA_TO_COVERAGE,
BLEND_MODE_PREMULT_ALPHA,
};

enum DepthDraw {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_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_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
Expand Down Expand Up @@ -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.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
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;
Expand Down Expand Up @@ -497,6 +508,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha";
actions.renames["PREMULT_ALPHA_FACTOR"] = "premult_alpha";
actions.renames["METALLIC"] = "metallic";
actions.renames["SPECULAR"] = "specular";
actions.renames["ROUGHNESS"] = "roughness";
Expand Down Expand Up @@ -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_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n";
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_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class SceneShaderForwardMobile {
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
BLEND_MODE_PREMULT_ALPHA,
BLEND_MODE_ALPHA_TO_COVERAGE
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,9 @@ vec3 encode24(vec3 v) {
void fragment_shader(in SceneData scene_data) {
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
vec3 vertex = vertex_interp;
#ifdef USE_MULTIVIEW
Expand Down Expand Up @@ -2458,6 +2461,10 @@ void fragment_shader(in SceneData scene_data) {

motion_vector = prev_position_uv - position_uv;
#endif

#if defined(PREMULT_ALPHA_USED) && !defined(MODE_RENDER_DEPTH)
frag_color.rgb *= premult_alpha;
#endif //PREMULT_ALPHA_USED
}

void main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,9 @@ void main() {
float clearcoat_roughness = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
#ifdef PREMULT_ALPHA_USED
float premult_alpha = 1.0;
#endif
#ifndef FOG_DISABLED
vec4 fog = vec4(0.0);
#endif // !FOG_DISABLED
Expand Down Expand Up @@ -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
// 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;
#ifdef PREMULT_ALPHA_USED
frag_color.rgb *= premult_alpha;
#endif

#endif //MODE_MULTIPLE_RENDER_TARGETS

Expand Down
3 changes: 2 additions & 1 deletion servers/rendering/shader_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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["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["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["METALLIC"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SPECULAR"] = ShaderLanguage::TYPE_FLOAT;
Expand Down Expand Up @@ -208,7 +209,7 @@ ShaderTypes::ShaderTypes() {

// 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_prepass_alpha") });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("depth_test_disabled") });
Expand Down
Loading