From bd161f9d0c0ca30434aa370ca154708a36cb4b04 Mon Sep 17 00:00:00 2001 From: Ed Swartz <875407+eswartz@users.noreply.github.com> Date: Mon, 6 May 2024 16:13:39 -0500 Subject: [PATCH] Enable geometry fade/transparency in the Mobile renderer This is mostly a copy-paste of similar changes in the Forward+ renderer, as hinted in https://github.com/godotengine/godot/issues/76774#issuecomment-1537237676 and https://github.com/godotengine/godot/pull/87231#pullrequestreview-2038713156, along with a tweak to the shader and pipeline model. The shader pipeline tweak involves distinguishing geometry instance-enabled transparency from material-enabled transparency. A material cannot support transparency on a per-instance level; a separate pipeline must be used when rendering. Originally in c571e4a7f4a5cc34fa9b7efeff37ee69fcf6249d this was a non-trivial refactoring in Forward+ (which in the past few years has evolved a few more times to account for the multitude of combinations allowed there). I opted to follow a similar sentiment to `SceneShaderForwardClustered::PipelineColorPassFlags` in a simpler `SceneShaderForwardMobile::PipelinePasses` enum, which only accounts for don't-care or opaque pipelines vs. color transparency-enabled ones. This multiplies the number of `PipelineCacheRD`s by two, but otherwise accomplishes the goals without adding unnecessary changes or shooting myself or others in the foot (I hope). BTW I also reorganized and removed some redundant checks in `RenderForwardClustered::_geometry_instance_add_surface_with_material` (since I was comparing this side-by-side with the `RenderForwardMobile` version, which seems better-organized). There is no functional change since `has_alpha` is the only variable used and includes all the checks anyway. --- doc/classes/GeometryInstance3D.xml | 6 +- scene/3d/visual_instance_3d.cpp | 8 +- .../render_forward_clustered.cpp | 6 +- .../forward_mobile/render_forward_mobile.cpp | 27 ++++++- .../forward_mobile/render_forward_mobile.h | 2 + .../scene_shader_forward_mobile.cpp | 79 ++++++++++--------- .../scene_shader_forward_mobile.h | 8 +- .../forward_mobile/scene_forward_mobile.glsl | 2 +- .../scene_forward_mobile_inc.glsl | 2 + 9 files changed, 89 insertions(+), 51 deletions(-) diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml index f4075af18697..e5bbf9fd1859 100644 --- a/doc/classes/GeometryInstance3D.xml +++ b/doc/classes/GeometryInstance3D.xml @@ -66,7 +66,7 @@ The transparency applied to the whole geometry (as a multiplier of the materials' existing transparency). [code]0.0[/code] is fully opaque, while [code]1.0[/code] is fully transparent. Values greater than [code]0.0[/code] (exclusive) will force the geometry's materials to go through the transparent pipeline, which is slower to render and can exhibit rendering issues due to incorrect transparency sorting. However, unlike using a transparent material, setting [member transparency] to a value greater than [code]0.0[/code] (exclusive) will [i]not[/i] disable shadow rendering. In spatial shaders, [code]1.0 - transparency[/code] is set as the default value of the [code]ALPHA[/code] built-in. [b]Note:[/b] [member transparency] is clamped between [code]0.0[/code] and [code]1.0[/code], so this property cannot be used to make transparent materials more opaque than they originally are. - [b]Note:[/b] Only supported when using the Forward+ rendering method. When using the Mobile or Compatibility rendering method, [member transparency] is ignored and is considered as always being [code]0.0[/code]. + [b]Note:[/b] Only supported when using the Forward+ or Mobile rendering methods. When using the Compatibility rendering method, [member transparency] is ignored and is considered as always being [code]0.0[/code]. Starting distance from which the GeometryInstance3D will be visible, taking [member visibility_range_begin_margin] into account as well. The default value of 0 is used to disable the range check. @@ -131,11 +131,11 @@ Will fade-out itself when reaching the limits of its own visibility range. This is slower than [constant VISIBILITY_RANGE_FADE_DISABLED], but it can provide smoother transitions. The fading range is determined by [member visibility_range_begin_margin] and [member visibility_range_end_margin]. - [b]Note:[/b] Only supported when using the Forward+ rendering method. When using the Mobile or Compatibility rendering method, this mode acts like [constant VISIBILITY_RANGE_FADE_DISABLED] but with hysteresis disabled. + [b]Note:[/b] Only supported when using the Forward+ or Mobile rendering methods. When using the Compatibility rendering method, this mode acts like [constant VISIBILITY_RANGE_FADE_DISABLED] but with hysteresis disabled. Will fade-in its visibility dependencies (see [member Node3D.visibility_parent]) when reaching the limits of its own visibility range. This is slower than [constant VISIBILITY_RANGE_FADE_DISABLED], but it can provide smoother transitions. The fading range is determined by [member visibility_range_begin_margin] and [member visibility_range_end_margin]. - [b]Note:[/b] Only supported when using the Forward+ rendering method. When using the Mobile or Compatibility rendering method, this mode acts like [constant VISIBILITY_RANGE_FADE_DISABLED] but with hysteresis disabled. + [b]Note:[/b] Only supported when using the Forward+ or Mobile rendering methods. When using the Compatibility rendering method, this mode acts like [constant VISIBILITY_RANGE_FADE_DISABLED] but with hysteresis disabled. diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index f14ae3a2856e..964a41a6f2e4 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -439,12 +439,12 @@ PackedStringArray GeometryInstance3D::get_configuration_warnings() const { warnings.push_back(RTR("The GeometryInstance3D is configured to fade out smoothly over distance, but the fade transition distance is set to 0.\nTo resolve this, increase Visibility Range End Margin above 0.")); } - if (!Math::is_zero_approx(transparency) && OS::get_singleton()->get_current_rendering_method() != "forward_plus") { - warnings.push_back(RTR("GeometryInstance3D transparency is only available when using the Forward+ rendering method.")); + if (!Math::is_zero_approx(transparency) && OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { + warnings.push_back(RTR("GeometryInstance3D transparency is only available when using the Forward+ or Mobile rendering methods.")); } - if ((visibility_range_fade_mode == VISIBILITY_RANGE_FADE_SELF || visibility_range_fade_mode == VISIBILITY_RANGE_FADE_DEPENDENCIES) && OS::get_singleton()->get_current_rendering_method() != "forward_plus") { - warnings.push_back(RTR("GeometryInstance3D visibility range transparency fade is only available when using the Forward+ rendering method.")); + if ((visibility_range_fade_mode == VISIBILITY_RANGE_FADE_SELF || visibility_range_fade_mode == VISIBILITY_RANGE_FADE_DEPENDENCIES) && OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { + warnings.push_back(RTR("GeometryInstance3D visibility range transparency fade is only available when using the Forward+ or Mobile rendering methods.")); } return warnings; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index f97ed3d21564..881334fd4e72 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -3739,9 +3739,9 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; - bool has_base_alpha = (p_material->shader_data->uses_alpha && (!p_material->shader_data->uses_alpha_clip || p_material->shader_data->uses_alpha_antialiasing)) || has_read_screen_alpha; + bool has_base_alpha = (p_material->shader_data->uses_alpha && (!p_material->shader_data->uses_alpha_clip || p_material->shader_data->uses_alpha_antialiasing)); bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; - bool has_alpha = has_base_alpha || has_blend_alpha; + bool has_alpha = has_base_alpha || has_blend_alpha || has_read_screen_alpha; uint32_t flags = 0; @@ -3765,7 +3765,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS; } - if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED) { + if (has_alpha || p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED) { //material is only meant for alpha pass flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA; if ((p_material->shader_data->uses_depth_prepass_alpha || p_material->shader_data->uses_alpha_antialiasing) && !(p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED)) { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index af190207db75..0f382d1b43e2 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -1077,7 +1077,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color // this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation //_setup_environment(p_render_data, is_reflection_probe, screen_size, p_default_bg_color, false); - RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); render_list_params.framebuffer_format = fb_format; render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass(); // Should now always be 0. @@ -1830,6 +1830,20 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const bool uses_lightmap = false; // bool uses_gi = false; + float fade_alpha = 1.0; + + if (inst->fade_near || inst->fade_far) { + float fade_dist = inst->transform.origin.distance_to(p_render_data->scene_data->cam_transform.origin); + // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. + if (inst->fade_far && fade_dist > inst->fade_far_begin) { + fade_alpha = Math::smoothstep(0.0f, 1.0f, 1.0f - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin)); + } else if (inst->fade_near && fade_dist < inst->fade_near_end) { + fade_alpha = Math::smoothstep(0.0f, 1.0f, (fade_dist - inst->fade_near_begin) / (inst->fade_near_end - inst->fade_near_begin)); + } + } + + fade_alpha *= inst->force_alpha * inst->parent_fade_alpha; + flags |= (uint32_t(fade_alpha * 255.0) << INSTANCE_DATA_FLAGS_FADE_SHIFT) & INSTANCE_DATA_FLAGS_FADE_MASK; if (p_render_list == RENDER_LIST_OPAQUE) { if (inst->lightmap_instance.is_valid()) { @@ -1935,6 +1949,11 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const #else bool force_alpha = false; #endif + + if (fade_alpha < 0.999) { + force_alpha = true; + } + if (!force_alpha && (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { rl->add_element(surf); } @@ -2146,6 +2165,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr RID xforms_uniform_set = surf->owner->transforms_uniform_set; SceneShaderForwardMobile::ShaderVersion shader_version = SceneShaderForwardMobile::SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. + SceneShaderForwardMobile::PipelinePasses color_pass = SceneShaderForwardMobile::PIPELINE_PASS_NOT_COLOR_OR_OPAQUE; switch (p_params->pass_mode) { case PASS_MODE_COLOR: @@ -2155,6 +2175,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr } else { shader_version = p_params->view_count > 1 ? SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS_MULTIVIEW : SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS; } + if (p_params->pass_mode == PASS_MODE_COLOR_TRANSPARENT) { + color_pass = SceneShaderForwardMobile::PIPELINE_PASS_COLOR_TRANSPARENT; + } } break; case PASS_MODE_SHADOW: { shader_version = p_params->view_count > 1 ? SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS_MULTIVIEW : SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS; @@ -2171,7 +2194,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr PipelineCacheRD *pipeline = nullptr; - pipeline = &shader->pipelines[cull_variant][primitive][shader_version]; + pipeline = &shader->pipelines[cull_variant][primitive][shader_version][color_pass]; RD::VertexFormatID vertex_format = -1; RID vertex_array_rd; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index b0fe5524499c..e97e0ab4ea16 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -392,6 +392,8 @@ class RenderForwardMobile : public RendererSceneRenderRD { INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16, INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF, + INSTANCE_DATA_FLAGS_FADE_SHIFT = 24, + INSTANCE_DATA_FLAGS_FADE_MASK = 0xFFUL << INSTANCE_DATA_FLAGS_FADE_SHIFT }; struct GeometryInstanceLightmapSH { diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index dd722cc2ddde..e979f7c11355 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -314,46 +314,49 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { raster_state.cull_mode = cull_mode_rd; raster_state.wireframe = wireframe; - RD::PipelineColorBlendState blend_state; - RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; - RD::PipelineMultisampleState multisample_state; - - if (uses_alpha || uses_blend_alpha) { - // only allow these flags to go through if we have some form of msaa - if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { - multisample_state.enable_alpha_to_coverage = true; - } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { - multisample_state.enable_alpha_to_coverage = true; - multisample_state.enable_alpha_to_one = true; - } + for (int l = 0; l < PIPELINE_PASS_COUNT; l++) { + RD::PipelineColorBlendState blend_state; + RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; + RD::PipelineMultisampleState multisample_state; + + if (l == PIPELINE_PASS_COLOR_TRANSPARENT) { + // only allow these flags to go through if we have some form of msaa + if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { + multisample_state.enable_alpha_to_coverage = true; + } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { + multisample_state.enable_alpha_to_coverage = true; + multisample_state.enable_alpha_to_one = true; + } - if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) { - blend_state = blend_state_blend; - if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) { - depth_stencil.enable_depth_write = false; //alpha does not draw depth + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) { + blend_state = blend_state_blend; + if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) { + depth_stencil.enable_depth_write = false; //alpha does not draw depth + } + } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) { + //none, blend state contains nothing + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { + blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way + } else { + pipelines[i][j][k][l].clear(); + continue; // do not use this version (will error if using it is attempted) + } + } else { // PIPELINE_PASS_NOT_COLOR_OR_OPAQUE + + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) { + blend_state = blend_state_opaque; + } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) { + //none, leave empty + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { + blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way + } else { + // ??? } - } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) { - //none, blend state contains nothing - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { - blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - } else { - pipelines[i][j][k].clear(); - continue; // do not use this version (will error if using it is attempted) - } - } else { - if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) { - blend_state = blend_state_opaque; - } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) { - //none, leave empty - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { - blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - } else { - // ??? } - } - RID shader_variant = shader_singleton->shader.version_get_shader(version, k); - pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); + RID shader_variant = shader_singleton->shader.version_get_shader(version, k); + pipelines[i][j][k][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); + } } } } @@ -757,7 +760,9 @@ void SceneShaderForwardMobile::set_default_specialization_constants(const Vector for (int i = 0; i < ShaderData::CULL_VARIANT_MAX; i++) { for (int j = 0; j < RS::PRIMITIVE_MAX; j++) { for (int k = 0; k < SHADER_VERSION_MAX; k++) { - E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants); + for (int l = 0; l < PIPELINE_PASS_COUNT; l++) { + E->self()->pipelines[i][j][k][l].update_specialization_constants(default_specialization_constants); + } } } } diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 833b06c1e31b..2fda661249b9 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -55,6 +55,12 @@ class SceneShaderForwardMobile { SHADER_VERSION_MAX }; + enum PipelinePasses { + PIPELINE_PASS_NOT_COLOR_OR_OPAQUE = 0, + PIPELINE_PASS_COLOR_TRANSPARENT = 1, + PIPELINE_PASS_COUNT = 2, + }; + struct ShaderData : public RendererRD::MaterialStorage::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, @@ -99,7 +105,7 @@ class SceneShaderForwardMobile { bool valid = false; RID version; uint64_t vertex_input_mask = 0; - PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; + PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX][PIPELINE_PASS_COUNT]; Vector texture_uniforms; diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 1637326b48c4..1bf3a789f4b0 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -765,7 +765,7 @@ void main() { float ao = 1.0; float ao_light_affect = 0.0; - float alpha = 1.0; + float alpha = float((instances.data[draw_call.instance_index].flags >> INSTANCE_FLAGS_FADE_SHIFT) & INSTANCE_FLAGS_FADE_MASK) / float(255.0); #if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) vec3 binormal = normalize(binormal_interp); diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 7674e905e1d4..378d522a0053 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -43,8 +43,10 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler; #define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) #define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15) #define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16 +#define INSTANCE_FLAGS_FADE_SHIFT 24 //3 bits of stride #define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF +#define INSTANCE_FLAGS_FADE_MASK 0xFF layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights { LightData data[];