Browse Source

Merge pull request #98825 from DarioSamo/mobile-scs

Add multiple specialization constants to Forward+ and Mobile.
Thaddeus Crews 10 tháng trước cách đây
mục cha
commit
c68ec6c369

+ 4 - 0
servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp

@@ -395,6 +395,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
 		RID xforms_uniform_set = surf->owner->transforms_uniform_set;
 
 		SceneShaderForwardClustered::ShaderSpecialization pipeline_specialization = p_params->base_specialization;
+		pipeline_specialization.multimesh = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH);
+		pipeline_specialization.multimesh_format_2d = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D);
+		pipeline_specialization.multimesh_has_color = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR);
+		pipeline_specialization.multimesh_has_custom_data = bool(surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA);
 
 		if constexpr (p_pass_mode == PASS_MODE_COLOR) {
 			pipeline_specialization.use_light_soft_shadows = element_info.uses_softshadow;

+ 4 - 0
servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp

@@ -374,6 +374,10 @@ void SceneShaderForwardClustered::ShaderData::_create_pipeline(PipelineKey p_pip
 	sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
 	specialization_constants.push_back(sc);
 
+	sc.constant_id = 1;
+	sc.int_value = p_pipeline_key.shader_specialization.packed_1;
+	specialization_constants.push_back(sc);
+
 	RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.color_pass_flags, p_pipeline_key.ubershader);
 	ERR_FAIL_COND(shader_rid.is_null());
 

+ 11 - 1
servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h

@@ -117,7 +117,17 @@ public:
 			uint32_t packed_0;
 		};
 
-		uint32_t packed_1;
+		union {
+			struct {
+				uint32_t multimesh : 1;
+				uint32_t multimesh_format_2d : 1;
+				uint32_t multimesh_has_color : 1;
+				uint32_t multimesh_has_custom_data : 1;
+			};
+
+			uint32_t packed_1;
+		};
+
 		uint32_t packed_2;
 	};
 

+ 20 - 13
servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

@@ -911,14 +911,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 	Color clear_color = p_default_bg_color;
 	bool load_color = false;
 	bool copy_canvas = false;
+	bool use_ambient_cubemap = false;
+	bool use_reflection_cubemap = false;
 
 	if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
 		clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
 	} else if (is_environment(p_render_data->environment)) {
+		RS::EnvironmentAmbientSource ambient_source = environment_get_ambient_source(p_render_data->environment);
 		RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
 		float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
 		bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
 		RS::EnvironmentReflectionSource reflection_source = environment_get_reflection_source(p_render_data->environment);
+		use_ambient_cubemap = (ambient_source == RS::ENV_AMBIENT_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY;
+		use_reflection_cubemap = (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY;
 
 		if (p_render_data->camera_attributes.is_valid()) {
 			bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
@@ -963,7 +968,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 		}
 
 		// setup sky if used for ambient, reflections, or background
-		if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
+		if (draw_sky || draw_sky_fog_only || (reflection_source == RS::ENV_REFLECTION_SOURCE_BG && bg_mode == RS::ENV_BG_SKY) || reflection_source == RS::ENV_REFLECTION_SOURCE_SKY || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY) {
 			RENDER_TIMESTAMP("Setup Sky");
 			RD::get_singleton()->draw_command_begin_label("Setup Sky");
 
@@ -1008,13 +1013,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 	SceneShaderForwardMobile::ShaderSpecialization base_specialization = scene_shader.default_specialization;
 
 	{
-		//figure out spec constants
-
-		if (p_render_data->directional_light_count > 0) {
-			base_specialization.use_directional_soft_shadows = p_render_data->directional_light_soft_shadows;
-		} else {
-			base_specialization.disable_directional_lights = true;
-		}
+		base_specialization.use_directional_soft_shadows = p_render_data->directional_light_count > 0 ? p_render_data->directional_light_soft_shadows : false;
+		base_specialization.directional_lights = p_render_data->directional_light_count;
 
 		if (!is_environment(p_render_data->environment) || !environment_get_fog_enabled(p_render_data->environment)) {
 			base_specialization.disable_fog = true;
@@ -1023,6 +1023,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
 		if (p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) {
 			base_specialization.use_depth_fog = true;
 		}
+
+		base_specialization.scene_use_ambient_cubemap = use_ambient_cubemap;
+		base_specialization.scene_use_reflection_cubemap = use_reflection_cubemap;
+		base_specialization.scene_roughness_limiter_enabled = p_render_data->render_buffers.is_valid() && screen_space_roughness_limiter_is_active();
 	}
 
 	{
@@ -2144,7 +2148,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
 		}
 
 		SceneShaderForwardMobile::ShaderSpecialization pipeline_specialization = p_params->base_specialization;
-		pipeline_specialization.is_multimesh = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH);
+		pipeline_specialization.multimesh = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH);
+		pipeline_specialization.multimesh_format_2d = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D);
+		pipeline_specialization.multimesh_has_color = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR);
+		pipeline_specialization.multimesh_has_custom_data = bool(inst->flags_cache & INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA);
 
 		SceneState::PushConstant push_constant;
 		push_constant.base_index = i + p_params->element_offset;
@@ -2165,10 +2172,10 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
 		} else {
 			pipeline_specialization.use_light_projector = inst->use_projector;
 			pipeline_specialization.use_light_soft_shadows = inst->use_soft_shadow;
-			pipeline_specialization.disable_omni_lights = inst->omni_light_count == 0;
-			pipeline_specialization.disable_spot_lights = inst->spot_light_count == 0;
-			pipeline_specialization.disable_reflection_probes = inst->reflection_probe_count == 0;
-			pipeline_specialization.disable_decals = inst->decals_count == 0;
+			pipeline_specialization.omni_lights = inst->omni_light_count;
+			pipeline_specialization.spot_lights = inst->spot_light_count;
+			pipeline_specialization.reflection_probes = inst->reflection_probe_count;
+			pipeline_specialization.decals = inst->decals_count;
 
 #ifdef DEBUG_ENABLED
 			if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) {

+ 1 - 0
servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp

@@ -237,6 +237,7 @@ void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeli
 			"VERSION:", p_pipeline_key.version,
 			"SPEC PACKED #0:", p_pipeline_key.shader_specialization.packed_0,
 			"SPEC PACKED #1:", p_pipeline_key.shader_specialization.packed_1,
+			"SPEC PACKED #2:", p_pipeline_key.shader_specialization.packed_2,
 			"RENDER PASS:", p_pipeline_key.render_pass,
 			"WIREFRAME:", p_pipeline_key.wireframe);
 #endif

+ 18 - 8
servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h

@@ -65,25 +65,35 @@ public:
 				uint32_t use_directional_soft_shadows : 1;
 				uint32_t decal_use_mipmaps : 1;
 				uint32_t projector_use_mipmaps : 1;
-				uint32_t disable_omni_lights : 1;
-				uint32_t disable_spot_lights : 1;
-				uint32_t disable_reflection_probes : 1;
-				uint32_t disable_directional_lights : 1;
-				uint32_t disable_decals : 1;
 				uint32_t disable_fog : 1;
 				uint32_t use_depth_fog : 1;
-				uint32_t is_multimesh : 1;
 				uint32_t use_lightmap_bicubic_filter : 1;
+				uint32_t multimesh : 1;
+				uint32_t multimesh_format_2d : 1;
+				uint32_t multimesh_has_color : 1;
+				uint32_t multimesh_has_custom_data : 1;
+				uint32_t scene_use_ambient_cubemap : 1;
+				uint32_t scene_use_reflection_cubemap : 1;
+				uint32_t scene_roughness_limiter_enabled : 1;
+				uint32_t padding : 5;
 				uint32_t soft_shadow_samples : 6;
 				uint32_t penumbra_shadow_samples : 6;
-				uint32_t directional_soft_shadow_samples : 6;
 			};
 
 			uint32_t packed_0;
 		};
 
 		union {
-			uint32_t directional_penumbra_shadow_samples : 6;
+			struct {
+				uint32_t directional_soft_shadow_samples : 6;
+				uint32_t directional_penumbra_shadow_samples : 6;
+				uint32_t omni_lights : 4;
+				uint32_t spot_lights : 4;
+				uint32_t reflection_probes : 4;
+				uint32_t directional_lights : 4;
+				uint32_t decals : 4;
+			};
+
 			uint32_t packed_1;
 		};
 

+ 17 - 27
servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl

@@ -211,6 +211,13 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec
 }
 #endif
 
+uint multimesh_stride() {
+	uint stride = sc_multimesh_format_2d() ? 2 : 3;
+	stride += sc_multimesh_has_color() ? 1 : 0;
+	stride += sc_multimesh_has_custom_data() ? 1 : 0;
+	return stride;
+}
+
 void vertex_shader(vec3 vertex_input,
 #ifdef NORMAL_USED
 		in vec3 normal_input,
@@ -219,7 +226,7 @@ void vertex_shader(vec3 vertex_input,
 		in vec3 tangent_input,
 		in vec3 binormal_input,
 #endif
-		in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
+		in uint instance_index, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
 	vec4 instance_custom = vec4(0.0);
 #if defined(COLOR_USED)
 	color_interp = color_attrib;
@@ -248,7 +255,7 @@ void vertex_shader(vec3 vertex_input,
 	mat4 matrix;
 	mat4 read_model_matrix = model_matrix;
 
-	if (is_multimesh) {
+	if (sc_multimesh()) {
 		//multimesh, instances are for it
 
 #ifdef USE_PARTICLE_TRAILS
@@ -296,25 +303,10 @@ void vertex_shader(vec3 vertex_input,
 #endif
 
 #else
-		uint stride = 0;
-		{
-			//TODO implement a small lookup table for the stride
-			if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
-				stride += 2;
-			} else {
-				stride += 3;
-			}
-			if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
-				stride += 1;
-			}
-			if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
-				stride += 1;
-			}
-		}
-
+		uint stride = multimesh_stride();
 		uint offset = stride * (gl_InstanceIndex + multimesh_offset);
 
-		if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+		if (sc_multimesh_format_2d()) {
 			matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
 			offset += 2;
 		} else {
@@ -322,14 +314,14 @@ void vertex_shader(vec3 vertex_input,
 			offset += 3;
 		}
 
-		if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+		if (sc_multimesh_has_color()) {
 #ifdef COLOR_USED
 			color_interp *= transforms.data[offset];
 #endif
 			offset += 1;
 		}
 
-		if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+		if (sc_multimesh_has_custom_data()) {
 			instance_custom = transforms.data[offset];
 		}
 
@@ -427,7 +419,7 @@ void vertex_shader(vec3 vertex_input,
 	// Then we combine the translations from the model matrix and the view matrix using emulated doubles.
 	// We add the result to the vertex and ignore the final lost precision.
 	vec3 model_origin = model_matrix[3].xyz;
-	if (is_multimesh) {
+	if (sc_multimesh()) {
 		vertex = mat3(matrix) * vertex;
 		model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
 	}
@@ -708,9 +700,7 @@ void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position
 
 void main() {
 	uint instance_index = draw_call.instance_index;
-
-	bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
-	if (!is_multimesh) {
+	if (!sc_multimesh()) {
 		instance_index += gl_InstanceIndex;
 	}
 
@@ -753,7 +743,7 @@ void main() {
 			prev_tangent,
 			prev_binormal,
 #endif
-			instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
+			instance_index, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
 #else
 	// Unused output.
 	vec4 screen_position;
@@ -792,7 +782,7 @@ void main() {
 			tangent,
 			binormal,
 #endif
-			instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
+			instance_index, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
 }
 
 #[fragment]

+ 25 - 4
servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl

@@ -59,6 +59,10 @@ uint sc_packed_0() {
 	return draw_call.sc_packed_0;
 }
 
+uint sc_packed_1() {
+	return draw_call.sc_packed_1;
+}
+
 uint uc_cull_mode() {
 	return (draw_call.uc_packed_0 >> 0) & 3U;
 }
@@ -67,11 +71,16 @@ uint uc_cull_mode() {
 
 // Pull the constants from the pipeline's specialization constants.
 layout(constant_id = 0) const uint pso_sc_packed_0 = 0;
+layout(constant_id = 1) const uint pso_sc_packed_1 = 0;
 
 uint sc_packed_0() {
 	return pso_sc_packed_0;
 }
 
+uint sc_packed_1() {
+	return pso_sc_packed_1;
+}
+
 #endif
 
 bool sc_use_forward_gi() {
@@ -122,6 +131,22 @@ uint sc_directional_penumbra_shadow_samples() {
 	return (sc_packed_0() >> 26) & 63U;
 }
 
+bool sc_multimesh() {
+	return ((sc_packed_1() >> 0) & 1U) != 0;
+}
+
+bool sc_multimesh_format_2d() {
+	return ((sc_packed_1() >> 1) & 1U) != 0;
+}
+
+bool sc_multimesh_has_color() {
+	return ((sc_packed_1() >> 2) & 1U) != 0;
+}
+
+bool sc_multimesh_has_custom_data() {
+	return ((sc_packed_1() >> 3) & 1U) != 0;
+}
+
 float sc_luminance_multiplier() {
 	// Not used in clustered renderer but we share some code with the mobile renderer that requires this.
 	return 1.0;
@@ -144,10 +169,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
 #define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
 #define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
 #define INSTANCE_FLAGS_PARTICLES (1 << 11)
-#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
-#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
-#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

+ 123 - 205
servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl

@@ -178,6 +178,13 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec
 }
 #endif
 
+uint multimesh_stride() {
+	uint stride = sc_multimesh_format_2d() ? 2 : 3;
+	stride += sc_multimesh_has_color() ? 1 : 0;
+	stride += sc_multimesh_has_custom_data() ? 1 : 0;
+	return stride;
+}
+
 void main() {
 	vec4 instance_custom = vec4(0.0);
 #if defined(COLOR_USED)
@@ -208,7 +215,7 @@ void main() {
 	mat4 matrix;
 	mat4 read_model_matrix = model_matrix;
 
-	if (sc_is_multimesh()) {
+	if (sc_multimesh()) {
 		//multimesh, instances are for it
 
 #ifdef USE_PARTICLE_TRAILS
@@ -256,25 +263,10 @@ void main() {
 #endif
 
 #else
-		uint stride = 0;
-		{
-			//TODO implement a small lookup table for the stride
-			if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
-				stride += 2;
-			} else {
-				stride += 3;
-			}
-			if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
-				stride += 1;
-			}
-			if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
-				stride += 1;
-			}
-		}
-
+		uint stride = multimesh_stride();
 		uint offset = stride * gl_InstanceIndex;
 
-		if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+		if (sc_multimesh_format_2d()) {
 			matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
 			offset += 2;
 		} else {
@@ -282,14 +274,14 @@ void main() {
 			offset += 3;
 		}
 
-		if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+		if (sc_multimesh_has_color()) {
 #ifdef COLOR_USED
 			color_interp *= transforms.data[offset];
 #endif
 			offset += 1;
 		}
 
-		if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+		if (sc_multimesh_has_custom_data()) {
 			instance_custom = transforms.data[offset];
 		}
 
@@ -404,7 +396,7 @@ void main() {
 	// Then we combine the translations from the model matrix and the view matrix using emulated doubles.
 	// We add the result to the vertex and ignore the final lost precision.
 	vec3 model_origin = model_matrix[3].xyz;
-	if (sc_is_multimesh()) {
+	if (sc_multimesh()) {
 		vertex = mat3(matrix) * vertex;
 		model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
 	}
@@ -461,50 +453,24 @@ void main() {
 	diffuse_light_interp = vec4(0.0);
 	specular_light_interp = vec4(0.0);
 
-	if (!sc_disable_omni_lights()) {
-		uint light_indices = instances.data[draw_call.instance_index].omni_lights.x;
-		for (uint i = 0; i < 8; i++) {
-			uint light_index = light_indices & 0xFF;
-			if (i == 3) {
-				light_indices = instances.data[draw_call.instance_index].omni_lights.y;
-			} else {
-				light_indices = light_indices >> 8;
-			}
-
-			if (light_index == 0xFF) {
-				break;
-			}
-
-			light_process_omni_vertex(light_index, vertex, view, normal, roughness,
-					diffuse_light_interp.rgb, specular_light_interp.rgb);
-		}
+	uvec2 omni_light_indices = instances.data[draw_call.instance_index].omni_lights;
+	for (uint i = 0; i < sc_omni_lights(); i++) {
+		uint light_index = (i > 3) ? ((omni_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_light_indices.x >> (i * 8)) & 0xFF);
+		light_process_omni_vertex(light_index, vertex, view, normal, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb);
 	}
 
-	if (!sc_disable_spot_lights()) {
-		uint light_indices = instances.data[draw_call.instance_index].spot_lights.x;
-		for (uint i = 0; i < 8; i++) {
-			uint light_index = light_indices & 0xFF;
-			if (i == 3) {
-				light_indices = instances.data[draw_call.instance_index].spot_lights.y;
-			} else {
-				light_indices = light_indices >> 8;
-			}
-
-			if (light_index == 0xFF) {
-				break;
-			}
-
-			light_process_spot_vertex(light_index, vertex, view, normal, roughness,
-					diffuse_light_interp.rgb, specular_light_interp.rgb);
-		}
+	uvec2 spot_light_indices = instances.data[draw_call.instance_index].spot_lights;
+	for (uint i = 0; i < sc_spot_lights(); i++) {
+		uint light_index = (i > 3) ? ((spot_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_light_indices.x >> (i * 8)) & 0xFF);
+		light_process_spot_vertex(light_index, vertex, view, normal, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb);
 	}
 
-	if (!sc_disable_directional_lights()) {
+	if (sc_directional_lights() > 0) {
 		// We process the first directional light separately as it may have shadows.
 		vec3 directional_diffuse = vec3(0.0);
 		vec3 directional_specular = vec3(0.0);
 
-		for (uint i = 0; i < scene_data.directional_light_count; i++) {
+		for (uint i = 0; i < sc_directional_lights(); i++) {
 			if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
 				continue; // Not masked, skip.
 			}
@@ -823,7 +789,7 @@ vec4 fog_process(vec3 vertex) {
 		float sun_total = 0.0;
 		vec3 view = normalize(vertex);
 
-		for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) {
+		for (uint i = 0; i < sc_directional_lights(); i++) {
 			vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy;
 			float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0);
 			fog_color += light_color * light_amount * scene_data_block.data.fog_sun_scatter;
@@ -1110,97 +1076,83 @@ void main() {
 	vec3 vertex_ddx = dFdx(vertex);
 	vec3 vertex_ddy = dFdy(vertex);
 
-	if (!sc_disable_decals()) { //Decals
-		// must implement
-
-		uint decal_indices = instances.data[draw_call.instance_index].decals.x;
-		for (uint i = 0; i < 8; i++) {
-			uint decal_index = decal_indices & 0xFF;
-			if (i == 3) {
-				decal_indices = instances.data[draw_call.instance_index].decals.y;
-			} else {
-				decal_indices = decal_indices >> 8;
-			}
+	uvec2 decal_indices = instances.data[draw_call.instance_index].decals;
+	for (uint i = 0; i < sc_decals(); i++) {
+		uint decal_index = (i > 3) ? ((decal_indices.y >> ((i - 4) * 8)) & 0xFF) : ((decal_indices.x >> (i * 8)) & 0xFF);
+		if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) {
+			continue; //not masked
+		}
 
-			if (decal_index == 0xFF) {
-				break;
-			}
+		vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
+		if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
+			continue; //out of decal
+		}
 
-			if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) {
-				continue; //not masked
-			}
+		float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
 
-			vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
-			if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
-				continue; //out of decal
-			}
+		if (decals.data[decal_index].normal_fade > 0.0) {
+			fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
+		}
 
-			float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
+		//we need ddx/ddy for mipmaps, so simulate them
+		vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
+		vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
 
-			if (decals.data[decal_index].normal_fade > 0.0) {
-				fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
+		if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
+			//has albedo
+			vec4 decal_albedo;
+			if (sc_decal_use_mipmaps()) {
+				decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+			} else {
+				decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
 			}
+			decal_albedo *= decals.data[decal_index].modulate;
+			decal_albedo.a *= fade;
+			albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
 
-			//we need ddx/ddy for mipmaps, so simulate them
-			vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
-			vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
-
-			if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
-				//has albedo
-				vec4 decal_albedo;
+			if (decals.data[decal_index].normal_rect != vec4(0.0)) {
+				vec3 decal_normal;
 				if (sc_decal_use_mipmaps()) {
-					decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+					decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
 				} else {
-					decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
-				}
-				decal_albedo *= decals.data[decal_index].modulate;
-				decal_albedo.a *= fade;
-				albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
-
-				if (decals.data[decal_index].normal_rect != vec4(0.0)) {
-					vec3 decal_normal;
-					if (sc_decal_use_mipmaps()) {
-						decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
-					} else {
-						decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
-					}
-					decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
-					decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
-					//convert to view space, use xzy because y is up
-					decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
-
-					normal = normalize(mix(normal, decal_normal, decal_albedo.a));
+					decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
 				}
+				decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
+				decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
+				//convert to view space, use xzy because y is up
+				decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
 
-				if (decals.data[decal_index].orm_rect != vec4(0.0)) {
-					vec3 decal_orm;
-					if (sc_decal_use_mipmaps()) {
-						decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
-					} else {
-						decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
-					}
-					ao = mix(ao, decal_orm.r, decal_albedo.a);
-					roughness = mix(roughness, decal_orm.g, decal_albedo.a);
-					metallic = mix(metallic, decal_orm.b, decal_albedo.a);
-				}
+				normal = normalize(mix(normal, decal_normal, decal_albedo.a));
 			}
 
-			if (decals.data[decal_index].emission_rect != vec4(0.0)) {
-				//emission is additive, so its independent from albedo
+			if (decals.data[decal_index].orm_rect != vec4(0.0)) {
+				vec3 decal_orm;
 				if (sc_decal_use_mipmaps()) {
-					emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+					decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
 				} else {
-					emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
+					decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
 				}
+				ao = mix(ao, decal_orm.r, decal_albedo.a);
+				roughness = mix(roughness, decal_orm.g, decal_albedo.a);
+				metallic = mix(metallic, decal_orm.b, decal_albedo.a);
+			}
+		}
+
+		if (decals.data[decal_index].emission_rect != vec4(0.0)) {
+			//emission is additive, so its independent from albedo
+			if (sc_decal_use_mipmaps()) {
+				emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+			} else {
+				emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
 			}
 		}
-	} //Decals
+	}
 #endif //!MODE_RENDER_DEPTH
 
 	/////////////////////// LIGHTING //////////////////////////////
 
 #ifdef NORMAL_USED
-	if (scene_data.roughness_limiter_enabled) {
+	if (sc_scene_roughness_limiter_enabled()) {
 		//https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
 		float roughness2 = roughness * roughness;
 		vec3 dndu = dFdx(normal), dndv = dFdy(normal);
@@ -1225,7 +1177,7 @@ void main() {
 
 #ifndef AMBIENT_LIGHT_DISABLED
 
-	if (scene_data.use_reflection_cubemap) {
+	if (sc_scene_use_reflection_cubemap()) {
 #ifdef LIGHT_ANISOTROPY_USED
 		// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
 		vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
@@ -1266,7 +1218,7 @@ void main() {
 	if (scene_data.use_ambient_light) {
 		ambient_light = scene_data.ambient_light_color_energy.rgb;
 
-		if (scene_data.use_ambient_cubemap) {
+		if (sc_scene_use_ambient_cubemap()) {
 			vec3 ambient_dir = scene_data.radiance_inverse_xform * normal;
 #ifdef USE_RADIANCE_CUBEMAP_ARRAY
 			vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb;
@@ -1285,7 +1237,7 @@ void main() {
 #endif // CUSTOM_IRRADIANCE_USED
 #ifdef LIGHT_CLEARCOAT_USED
 
-	if (scene_data.use_reflection_cubemap) {
+	if (sc_scene_use_reflection_cubemap()) {
 		vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map
 		float NoV = max(dot(n, view), 0.0001);
 		vec3 ref_vec = reflect(-view, n);
@@ -1393,12 +1345,10 @@ void main() {
 
 	// skipping ssao, do we remove ssao totally?
 
-	if (!sc_disable_reflection_probes()) { //Reflection probes
+	if (sc_reflection_probes() > 0) {
 		vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
 		vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
 
-		uint reflection_indices = instances.data[draw_call.instance_index].reflection_probes.x;
-
 #ifdef LIGHT_ANISOTROPY_USED
 		// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
 		vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
@@ -1411,18 +1361,9 @@ void main() {
 		vec3 ref_vec = normalize(reflect(-view, bent_normal));
 		ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
 
-		for (uint i = 0; i < 8; i++) {
-			uint reflection_index = reflection_indices & 0xFF;
-			if (i == 3) {
-				reflection_indices = instances.data[draw_call.instance_index].reflection_probes.y;
-			} else {
-				reflection_indices = reflection_indices >> 8;
-			}
-
-			if (reflection_index == 0xFF) {
-				break;
-			}
-
+		uvec2 reflection_indices = instances.data[draw_call.instance_index].reflection_probes;
+		for (uint i = 0; i < sc_reflection_probes(); i++) {
+			uint reflection_index = (i > 3) ? ((reflection_indices.y >> ((i - 4) * 8)) & 0xFF) : ((reflection_indices.x >> (i * 8)) & 0xFF);
 			reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
 		}
 
@@ -1487,7 +1428,7 @@ void main() {
 	specular_light += specular_light_interp.rgb * f0;
 #endif
 
-	if (!sc_disable_directional_lights()) { //directional light
+	if (sc_directional_lights() > 0) {
 #ifndef SHADOWS_DISABLED
 		// Do shadow and lighting in two passes to reduce register pressure
 		uint shadow0 = 0;
@@ -1497,7 +1438,7 @@ void main() {
 		// Only process the first light's shadow for vertex lighting.
 		for (uint i = 0; i < 1; i++) {
 #else
-		for (uint i = 0; i < scene_data.directional_light_count; i++) {
+		for (uint i = 0; i < sc_directional_lights(); i++) {
 #endif
 
 			if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
@@ -1612,7 +1553,7 @@ void main() {
 #endif // SHADOWS_DISABLED
 
 #ifndef USE_VERTEX_LIGHTING
-		for (uint i = 0; i < scene_data.directional_light_count; i++) {
+		for (uint i = 0; i < sc_directional_lights(); i++) {
 			if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
 				continue; //not masked
 			}
@@ -1678,95 +1619,72 @@ void main() {
 	} //directional light
 
 #ifndef USE_VERTEX_LIGHTING
-	if (!sc_disable_omni_lights()) { //omni lights
-		uint light_indices = instances.data[draw_call.instance_index].omni_lights.x;
-		for (uint i = 0; i < 8; i++) {
-			uint light_index = light_indices & 0xFF;
-			if (i == 3) {
-				light_indices = instances.data[draw_call.instance_index].omni_lights.y;
-			} else {
-				light_indices = light_indices >> 8;
-			}
-
-			if (light_index == 0xFF) {
-				break;
-			}
+	uvec2 omni_indices = instances.data[draw_call.instance_index].omni_lights;
+	for (uint i = 0; i < sc_omni_lights(); i++) {
+		uint light_index = (i > 3) ? ((omni_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_indices.x >> (i * 8)) & 0xFF);
 
-			float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
+		float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
 
-			shadow = blur_shadow(shadow);
+		shadow = blur_shadow(shadow);
 
-			// Fragment lighting
-			light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
+		// Fragment lighting
+		light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
 #ifdef LIGHT_BACKLIGHT_USED
-					backlight,
+				backlight,
 #endif
 /*
 #ifdef LIGHT_TRANSMITTANCE_USED
-					transmittance_color,
-					transmittance_depth,
-					transmittance_boost,
+				transmittance_color,
+				transmittance_depth,
+				transmittance_boost,
 #endif
 */
 #ifdef LIGHT_RIM_USED
-					rim,
-					rim_tint,
+				rim,
+				rim_tint,
 #endif
 #ifdef LIGHT_CLEARCOAT_USED
-					clearcoat, clearcoat_roughness, normalize(normal_interp),
+				clearcoat, clearcoat_roughness, normalize(normal_interp),
 #endif
 #ifdef LIGHT_ANISOTROPY_USED
-					tangent,
-					binormal, anisotropy,
+				tangent,
+				binormal, anisotropy,
 #endif
-					diffuse_light, specular_light);
-		}
-	} //omni lights
-
-	if (!sc_disable_spot_lights()) { //spot lights
-
-		uint light_indices = instances.data[draw_call.instance_index].spot_lights.x;
-		for (uint i = 0; i < 8; i++) {
-			uint light_index = light_indices & 0xFF;
-			if (i == 3) {
-				light_indices = instances.data[draw_call.instance_index].spot_lights.y;
-			} else {
-				light_indices = light_indices >> 8;
-			}
+				diffuse_light, specular_light);
+	}
 
-			if (light_index == 0xFF) {
-				break;
-			}
+	uvec2 spot_indices = instances.data[draw_call.instance_index].spot_lights;
+	for (uint i = 0; i < sc_spot_lights(); i++) {
+		uint light_index = (i > 3) ? ((spot_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_indices.x >> (i * 8)) & 0xFF);
 
-			float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
+		float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
 
-			shadow = blur_shadow(shadow);
+		shadow = blur_shadow(shadow);
 
-			light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
+		light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
 #ifdef LIGHT_BACKLIGHT_USED
-					backlight,
+				backlight,
 #endif
 /*
 #ifdef LIGHT_TRANSMITTANCE_USED
-					transmittance_color,
-					transmittance_depth,
-					transmittance_boost,
+				transmittance_color,
+				transmittance_depth,
+				transmittance_boost,
 #endif
 */
 #ifdef LIGHT_RIM_USED
-					rim,
-					rim_tint,
+				rim,
+				rim_tint,
 #endif
 #ifdef LIGHT_CLEARCOAT_USED
-					clearcoat, clearcoat_roughness, normalize(normal_interp),
+				clearcoat, clearcoat_roughness, normalize(normal_interp),
 #endif
 #ifdef LIGHT_ANISOTROPY_USED
-					tangent,
-					binormal, anisotropy,
+				tangent,
+				binormal, anisotropy,
 #endif
-					diffuse_light, specular_light);
-		}
-	} //spot lights
+				diffuse_light, specular_light);
+	}
 #endif // !VERTEX_LIGHTING
 
 #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)

+ 37 - 17
servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl

@@ -95,56 +95,80 @@ bool sc_projector_use_mipmaps() {
 	return ((sc_packed_0() >> 4) & 1U) != 0;
 }
 
-bool sc_disable_omni_lights() {
+bool sc_disable_fog() {
 	return ((sc_packed_0() >> 5) & 1U) != 0;
 }
 
-bool sc_disable_spot_lights() {
+bool sc_use_depth_fog() {
 	return ((sc_packed_0() >> 6) & 1U) != 0;
 }
 
-bool sc_disable_reflection_probes() {
+bool sc_use_lightmap_bicubic_filter() {
 	return ((sc_packed_0() >> 7) & 1U) != 0;
 }
 
-bool sc_disable_directional_lights() {
+bool sc_multimesh() {
 	return ((sc_packed_0() >> 8) & 1U) != 0;
 }
 
-bool sc_disable_decals() {
+bool sc_multimesh_format_2d() {
 	return ((sc_packed_0() >> 9) & 1U) != 0;
 }
 
-bool sc_disable_fog() {
+bool sc_multimesh_has_color() {
 	return ((sc_packed_0() >> 10) & 1U) != 0;
 }
 
-bool sc_use_depth_fog() {
+bool sc_multimesh_has_custom_data() {
 	return ((sc_packed_0() >> 11) & 1U) != 0;
 }
 
-bool sc_is_multimesh() {
+bool sc_scene_use_ambient_cubemap() {
 	return ((sc_packed_0() >> 12) & 1U) != 0;
 }
 
-bool sc_use_lightmap_bicubic_filter() {
+bool sc_scene_use_reflection_cubemap() {
 	return ((sc_packed_0() >> 13) & 1U) != 0;
 }
 
+bool sc_scene_roughness_limiter_enabled() {
+	return ((sc_packed_0() >> 14) & 1U) != 0;
+}
+
 uint sc_soft_shadow_samples() {
-	return (sc_packed_0() >> 14) & 63U;
+	return (sc_packed_0() >> 20) & 63U;
 }
 
 uint sc_penumbra_shadow_samples() {
-	return (sc_packed_0() >> 20) & 63U;
+	return (sc_packed_0() >> 26) & 63U;
 }
 
 uint sc_directional_soft_shadow_samples() {
-	return (sc_packed_0() >> 26) & 63U;
+	return (sc_packed_1() >> 0) & 63U;
 }
 
 uint sc_directional_penumbra_shadow_samples() {
-	return (sc_packed_1() >> 0) & 63U;
+	return (sc_packed_1() >> 6) & 63U;
+}
+
+uint sc_omni_lights() {
+	return (sc_packed_1() >> 12) & 15U;
+}
+
+uint sc_spot_lights() {
+	return (sc_packed_1() >> 16) & 15U;
+}
+
+uint sc_reflection_probes() {
+	return (sc_packed_1() >> 20) & 15U;
+}
+
+uint sc_directional_lights() {
+	return (sc_packed_1() >> 24) & 15U;
+}
+
+uint sc_decals() {
+	return (sc_packed_1() >> 28) & 15U;
 }
 
 float sc_luminance_multiplier() {
@@ -166,10 +190,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
 #define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
 #define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
 #define INSTANCE_FLAGS_PARTICLES (1 << 11)
-#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
-#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
 #define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
 //3 bits of stride
 #define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF