From 79b1a6defc2b6b7f73775b295e1751a359e279f4 Mon Sep 17 00:00:00 2001 From: Kaleb Reid <78945904+Kaleb-Reid@users.noreply.github.com> Date: Tue, 10 Jun 2025 16:01:22 -0700 Subject: [PATCH] Implement DirectionalLight3D cull masks in Compatibility --- drivers/gles3/rasterizer_scene_gles3.cpp | 8 +++ drivers/gles3/rasterizer_scene_gles3.h | 5 +- drivers/gles3/shaders/scene.glsl | 68 +++++++++++++--------- drivers/gles3/shaders/sky.glsl | 7 ++- drivers/gles3/storage/material_storage.cpp | 8 +-- 5 files changed, 62 insertions(+), 34 deletions(-) diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index f82614998ec..3b9968bc97d 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1712,6 +1712,8 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR); + light_data.mask = light_storage->light_get_cull_mask(base); + light_data.shadow_opacity = (p_using_shadows && light_storage->light_has_shadow(base)) ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) : 0.0; @@ -3428,6 +3430,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, // Render directional lights. uint32_t shadow_id = MAX_DIRECTIONAL_LIGHTS - 1 - (pass - int32_t(inst->light_passes.size())); + if (!(scene_state.directional_lights[shadow_id].mask & inst->layer_mask)) { + // Disable additive lighting when masks are not overlapping. + spec_constants &= ~SceneShaderGLES3::USE_ADDITIVE_LIGHTING; + } if (pass == 0 && inst->lightmap_instance.is_valid() && scene_state.directional_lights[shadow_id].bake_mode == RenderingServer::LIGHT_BAKE_STATIC) { // Disable additive lighting with a static light and a lightmap. spec_constants &= ~SceneShaderGLES3::USE_ADDITIVE_LIGHTING; @@ -3674,6 +3680,8 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params, if (p_pass_mode == PASS_MODE_MATERIAL) { material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::UV_OFFSET, p_params->uv_offset, shader->version, instance_variant, spec_constants); + } else if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) { + material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LAYER_MASK, inst->layer_mask, shader->version, instance_variant, spec_constants); } // Can be index count or vertex count diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 3f049b20a3a..e2d2284facc 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -203,10 +203,11 @@ private: float color[3]; float size; - uint32_t enabled; // For use by SkyShaders - uint32_t bake_mode; + uint32_t enabled : 1; // For use by SkyShaders + uint32_t bake_mode : 2; float shadow_opacity; float specular; + uint32_t mask; }; static_assert(sizeof(DirectionalLightData) % 16 == 0, "DirectionalLightData size must be a multiple of 16 bytes"); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 54c3e905870..fc77f9bde82 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -290,19 +290,19 @@ struct DirectionalLightData { mediump float energy; mediump vec3 color; mediump float size; - lowp uint unused; - lowp uint bake_mode; + lowp uint enabled_bake_mode; mediump float shadow_opacity; mediump float specular; + highp uint mask; }; layout(std140) uniform DirectionalLights { // ubo:7 DirectionalLightData directional_lights[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; }; -#define LIGHT_BAKE_DISABLED 0u -#define LIGHT_BAKE_STATIC 1u -#define LIGHT_BAKE_DYNAMIC 2u +#define DIRECTIONAL_LIGHT_ENABLED uint(1 << 0) +#define DIRECTIONAL_LIGHT_BAKE_STATIC uint(1 << 1) +#define DIRECTIONAL_LIGHT_BAKE_DYNAMIC uint(1 << 2) #endif // !DISABLE_LIGHT_DIRECTIONAL // Omni and spot light data. @@ -465,6 +465,7 @@ uniform highp vec3 compressed_aabb_position; uniform highp vec3 compressed_aabb_size; uniform highp vec4 uv_scale; uniform highp uint instance_offset; +uniform highp uint layer_mask; #if defined(RENDER_MOTION_VECTORS) uniform highp mat4 prev_world_transform; @@ -814,8 +815,11 @@ void vertex_shader(vec4 vertex_angle_attrib_input, #ifdef BASE_PASS #ifndef DISABLE_LIGHT_DIRECTIONAL for (uint i = uint(0); i < scene_data_input.directional_light_count; i++) { + if (!bool(directional_lights[i].mask & layer_mask)) { + continue; + } #if defined(USE_LIGHTMAP) && !defined(DISABLE_LIGHTMAP) - if (directional_lights[i].bake_mode == LIGHT_BAKE_STATIC) { + if (bool(directional_lights[i].enabled_bake_mode & DIRECTIONAL_LIGHT_BAKE_STATIC)) { continue; } #endif @@ -846,9 +850,11 @@ void vertex_shader(vec4 vertex_angle_attrib_input, additive_specular_light_interp = vec3(0.0); #if !defined(ADDITIVE_OMNI) && !defined(ADDITIVE_SPOT) - light_compute(normal_interp, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, roughness, - additive_diffuse_light_interp.rgb, - additive_specular_light_interp.rgb); + if (bool(directional_lights[directional_shadow_index].mask & layer_mask)) { + light_compute(normal_interp, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, roughness, + additive_diffuse_light_interp.rgb, + additive_specular_light_interp.rgb); + } #endif // !defined(ADDITIVE_OMNI) && !defined(ADDITIVE_SPOT) #ifdef ADDITIVE_OMNI @@ -1187,11 +1193,12 @@ multiview_data_block; uniform highp mat4 world_transform; uniform highp uint instance_offset; +uniform highp uint layer_mask; uniform highp uint model_flags; -#define LIGHT_BAKE_DISABLED 0u -#define LIGHT_BAKE_STATIC 1u -#define LIGHT_BAKE_DYNAMIC 2u +#define DIRECTIONAL_LIGHT_ENABLED uint(1 << 0) +#define DIRECTIONAL_LIGHT_BAKE_STATIC uint(1 << 1) +#define DIRECTIONAL_LIGHT_BAKE_DYNAMIC uint(1 << 2) #ifndef MODE_RENDER_DEPTH #ifdef USE_VERTEX_LIGHTING @@ -1212,10 +1219,10 @@ struct DirectionalLightData { mediump float energy; mediump vec3 color; mediump float size; - lowp uint unused; - lowp uint bake_mode; + lowp uint enabled_bake_mode; mediump float shadow_opacity; mediump float specular; + highp uint mask; }; layout(std140) uniform DirectionalLights { // ubo:7 @@ -2369,8 +2376,11 @@ void main() { #ifndef DISABLE_LIGHT_DIRECTIONAL for (uint i = uint(0); i < scene_data_block.data.directional_light_count; i++) { + if (!bool(directional_lights[i].mask & layer_mask)) { + continue; + } #if defined(USE_LIGHTMAP) && !defined(DISABLE_LIGHTMAP) - if (directional_lights[i].bake_mode == LIGHT_BAKE_STATIC) { + if (bool(directional_lights[i].enabled_bake_mode & DIRECTIONAL_LIGHT_BAKE_STATIC)) { continue; } #endif @@ -2688,26 +2698,30 @@ void main() { #endif // SHADOWS_DISABLED #ifndef USE_VERTEX_LIGHTING - light_compute(normal, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].size, directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, directional_shadow, f0, roughness, metallic, directional_lights[directional_shadow_index].specular, albedo, alpha, screen_uv, + if (bool(directional_lights[directional_shadow_index].mask & layer_mask)) { + light_compute(normal, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].size, directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, directional_shadow, f0, roughness, metallic, directional_lights[directional_shadow_index].specular, albedo, alpha, screen_uv, #ifdef LIGHT_BACKLIGHT_USED - backlight, + backlight, #endif #ifdef LIGHT_RIM_USED - rim, rim_tint, + rim, rim_tint, #endif #ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_roughness, geo_normal, + clearcoat, clearcoat_roughness, geo_normal, #endif // LIGHT_CLEARCOAT_USED #ifdef LIGHT_ANISOTROPY_USED - binormal, - tangent, anisotropy, + binormal, + tangent, anisotropy, #endif - diffuse_light, - specular_light); -#else - // Just apply shadows to vertex lighting. - diffuse_light *= directional_shadow; - specular_light *= directional_shadow; + diffuse_light, + specular_light); + } else { +#endif // !USE_VERTEX_LIGHTING + // Just apply shadows to vertex lighting. + diffuse_light *= directional_shadow; + specular_light *= directional_shadow; +#ifndef USE_VERTEX_LIGHTING + } #endif // !USE_VERTEX_LIGHTING #endif // !defined(ADDITIVE_OMNI) && !defined(ADDITIVE_SPOT) diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index dd0bd7962ee..a65f87e8f6e 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -59,7 +59,10 @@ layout(std140) uniform GlobalShaderUniformData { //ubo:1 struct DirectionalLightData { vec4 direction_energy; vec4 color_size; - bool enabled; + uint enabled_bake_mode; + float shadow_opacity; + float specular; + uint mask; }; layout(std140) uniform DirectionalLights { //ubo:4 @@ -67,6 +70,8 @@ layout(std140) uniform DirectionalLights { //ubo:4 } directional_lights; +#define DIRECTIONAL_LIGHT_ENABLED uint(1 << 0) + /* clang-format off */ #ifdef MATERIAL_UNIFORMS_USED diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 87244fcc20c..d994a2e5c3e 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1512,22 +1512,22 @@ MaterialStorage::MaterialStorage() { actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color"; actions.renames["RADIANCE"] = "radiance"; actions.renames["FOG"] = "custom_fog"; - actions.renames["LIGHT0_ENABLED"] = "directional_lights.data[0].enabled"; + actions.renames["LIGHT0_ENABLED"] = "bool(directional_lights.data[0].enabled_bake_mode & DIRECTIONAL_LIGHT_ENABLED)"; actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction_energy.xyz"; actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].direction_energy.w"; actions.renames["LIGHT0_COLOR"] = "directional_lights.data[0].color_size.xyz"; actions.renames["LIGHT0_SIZE"] = "directional_lights.data[0].color_size.w"; - actions.renames["LIGHT1_ENABLED"] = "directional_lights.data[1].enabled"; + actions.renames["LIGHT1_ENABLED"] = "bool(directional_lights.data[1].enabled_bake_mode & DIRECTIONAL_LIGHT_ENABLED)"; actions.renames["LIGHT1_DIRECTION"] = "directional_lights.data[1].direction_energy.xyz"; actions.renames["LIGHT1_ENERGY"] = "directional_lights.data[1].direction_energy.w"; actions.renames["LIGHT1_COLOR"] = "directional_lights.data[1].color_size.xyz"; actions.renames["LIGHT1_SIZE"] = "directional_lights.data[1].color_size.w"; - actions.renames["LIGHT2_ENABLED"] = "directional_lights.data[2].enabled"; + actions.renames["LIGHT2_ENABLED"] = "bool(directional_lights.data[2].enabled_bake_mode & DIRECTIONAL_LIGHT_ENABLED)"; actions.renames["LIGHT2_DIRECTION"] = "directional_lights.data[2].direction_energy.xyz"; actions.renames["LIGHT2_ENERGY"] = "directional_lights.data[2].direction_energy.w"; actions.renames["LIGHT2_COLOR"] = "directional_lights.data[2].color_size.xyz"; actions.renames["LIGHT2_SIZE"] = "directional_lights.data[2].color_size.w"; - actions.renames["LIGHT3_ENABLED"] = "directional_lights.data[3].enabled"; + actions.renames["LIGHT3_ENABLED"] = "bool(directional_lights.data[3].enabled_bake_mode & DIRECTIONAL_LIGHT_ENABLED)"; actions.renames["LIGHT3_DIRECTION"] = "directional_lights.data[3].direction_energy.xyz"; actions.renames["LIGHT3_ENERGY"] = "directional_lights.data[3].direction_energy.w"; actions.renames["LIGHT3_COLOR"] = "directional_lights.data[3].color_size.xyz";