2
0
Эх сурвалжийг харах

Reorganize renderer code.

So it can hopefully be made more cache efficient afterwards.
reduz 4 жил өмнө
parent
commit
9a2f18f8e7

+ 15 - 10
core/templates/rid.h

@@ -40,30 +40,35 @@ class RID {
 	uint64_t _id = 0;
 	uint64_t _id = 0;
 
 
 public:
 public:
-	_FORCE_INLINE_ bool operator==(const RID &p_rid) const {
+	_ALWAYS_INLINE_ bool operator==(const RID &p_rid) const {
 		return _id == p_rid._id;
 		return _id == p_rid._id;
 	}
 	}
-	_FORCE_INLINE_ bool operator<(const RID &p_rid) const {
+	_ALWAYS_INLINE_ bool operator<(const RID &p_rid) const {
 		return _id < p_rid._id;
 		return _id < p_rid._id;
 	}
 	}
-	_FORCE_INLINE_ bool operator<=(const RID &p_rid) const {
+	_ALWAYS_INLINE_ bool operator<=(const RID &p_rid) const {
 		return _id <= p_rid._id;
 		return _id <= p_rid._id;
 	}
 	}
-	_FORCE_INLINE_ bool operator>(const RID &p_rid) const {
+	_ALWAYS_INLINE_ bool operator>(const RID &p_rid) const {
 		return _id > p_rid._id;
 		return _id > p_rid._id;
 	}
 	}
-	_FORCE_INLINE_ bool operator>=(const RID &p_rid) const {
+	_ALWAYS_INLINE_ bool operator>=(const RID &p_rid) const {
 		return _id >= p_rid._id;
 		return _id >= p_rid._id;
 	}
 	}
-	_FORCE_INLINE_ bool operator!=(const RID &p_rid) const {
+	_ALWAYS_INLINE_ bool operator!=(const RID &p_rid) const {
 		return _id != p_rid._id;
 		return _id != p_rid._id;
 	}
 	}
-	_FORCE_INLINE_ bool is_valid() const { return _id != 0; }
-	_FORCE_INLINE_ bool is_null() const { return _id == 0; }
+	_ALWAYS_INLINE_ bool is_valid() const { return _id != 0; }
+	_ALWAYS_INLINE_ bool is_null() const { return _id == 0; }
 
 
-	_FORCE_INLINE_ uint64_t get_id() const { return _id; }
+	static _ALWAYS_INLINE_ RID from_uint64(uint64_t p_id) {
+		RID _rid;
+		_rid._id = p_id;
+		return _rid;
+	}
+	_ALWAYS_INLINE_ uint64_t get_id() const { return _id; }
 
 
-	_FORCE_INLINE_ RID() {}
+	_ALWAYS_INLINE_ RID() {}
 };
 };
 
 
 #endif // RID_H
 #endif // RID_H

+ 242 - 76
servers/rendering/renderer_rd/renderer_scene_render_forward.cpp

@@ -815,7 +815,7 @@ void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_element
 		bool store_transform = true;
 		bool store_transform = true;
 		id.flags = 0;
 		id.flags = 0;
 		id.mask = e->instance->layer_mask;
 		id.mask = e->instance->layer_mask;
-		id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0;
+		id.instance_uniforms_ofs = e->instance->shader_parameters_offset >= 0 ? e->instance->shader_parameters_offset : 0;
 
 
 		if (e->instance->base_type == RS::INSTANCE_MULTIMESH) {
 		if (e->instance->base_type == RS::INSTANCE_MULTIMESH) {
 			id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
 			id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -877,26 +877,32 @@ void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_element
 			continue;
 			continue;
 		}
 		}
 
 
-		if (e->instance->lightmap) {
-			int32_t lightmap_index = storage->lightmap_get_array_index(e->instance->lightmap->base);
-			if (lightmap_index >= 0) {
-				id.gi_offset = lightmap_index;
+		if (e->instance->lightmap_instance.is_valid()) {
+			int32_t lightmap_cull_index = -1;
+			for (uint32_t j = 0; j < scene_state.lightmaps_used; j++) {
+				if (scene_state.lightmap_ids[j] == e->instance->lightmap_instance) {
+					lightmap_cull_index = j;
+					break;
+				}
+			}
+			if (lightmap_cull_index >= 0) {
+				id.gi_offset = 0;
 				id.gi_offset |= e->instance->lightmap_slice_index << 12;
 				id.gi_offset |= e->instance->lightmap_slice_index << 12;
-				id.gi_offset |= e->instance->lightmap_cull_index << 20;
+				id.gi_offset |= lightmap_cull_index << 20;
 				id.lightmap_uv_scale[0] = e->instance->lightmap_uv_scale.position.x;
 				id.lightmap_uv_scale[0] = e->instance->lightmap_uv_scale.position.x;
 				id.lightmap_uv_scale[1] = e->instance->lightmap_uv_scale.position.y;
 				id.lightmap_uv_scale[1] = e->instance->lightmap_uv_scale.position.y;
 				id.lightmap_uv_scale[2] = e->instance->lightmap_uv_scale.size.width;
 				id.lightmap_uv_scale[2] = e->instance->lightmap_uv_scale.size.width;
 				id.lightmap_uv_scale[3] = e->instance->lightmap_uv_scale.size.height;
 				id.lightmap_uv_scale[3] = e->instance->lightmap_uv_scale.size.height;
 				id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP;
 				id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP;
-				if (storage->lightmap_uses_spherical_harmonics(e->instance->lightmap->base)) {
+				if (scene_state.lightmap_has_sh[lightmap_cull_index]) {
 					id.flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP;
 					id.flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP;
 				}
 				}
 			} else {
 			} else {
 				id.gi_offset = 0xFFFFFFFF;
 				id.gi_offset = 0xFFFFFFFF;
 			}
 			}
-		} else if (!e->instance->lightmap_sh.is_empty()) {
+		} else if (e->instance->lightmap_sh) {
 			if (lightmap_captures_used < scene_state.max_lightmap_captures) {
 			if (lightmap_captures_used < scene_state.max_lightmap_captures) {
-				const Color *src_capture = e->instance->lightmap_sh.ptr();
+				const Color *src_capture = e->instance->lightmap_sh;
 				LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used];
 				LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used];
 				for (int j = 0; j < 9; j++) {
 				for (int j = 0; j < 9; j++) {
 					lcd.sh[j * 4 + 0] = src_capture[j].r;
 					lcd.sh[j * 4 + 0] = src_capture[j].r;
@@ -914,9 +920,9 @@ void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_element
 				id.flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;
 				id.flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;
 			}
 			}
 
 
-			if (!low_end && !e->instance->gi_probe_instances.is_empty()) {
+			if (!low_end && e->instance->gi_probe_instance_count > 0) {
 				uint32_t written = 0;
 				uint32_t written = 0;
-				for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) {
+				for (uint32_t j = 0; j < e->instance->gi_probe_instance_count; j++) {
 					RID probe = e->instance->gi_probe_instances[j];
 					RID probe = e->instance->gi_probe_instances[j];
 
 
 					uint32_t index = gi_probe_instance_get_render_index(probe);
 					uint32_t index = gi_probe_instance_get_render_index(probe);
@@ -937,7 +943,7 @@ void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_element
 					id.gi_offset |= 0xFFFF0000;
 					id.gi_offset |= 0xFFFF0000;
 				}
 				}
 			} else {
 			} else {
-				if (p_has_sdfgi && (e->instance->baked_light || e->instance->dynamic_gi)) {
+				if (p_has_sdfgi && (e->instance->use_baked_light || e->instance->use_dynamic_gi)) {
 					id.flags |= INSTANCE_DATA_FLAG_USE_SDFGI;
 					id.flags |= INSTANCE_DATA_FLAG_USE_SDFGI;
 				}
 				}
 				id.gi_offset = 0xFFFFFFFF;
 				id.gi_offset = 0xFFFFFFFF;
@@ -984,7 +990,7 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
 		//find cull variant
 		//find cull variant
 		ShaderData::CullVariant cull_variant;
 		ShaderData::CullVariant cull_variant;
 
 
-		if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) {
+		if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_double_sided_shaodows)) {
 			cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
 			cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
 		} else {
 		} else {
 			bool mirror = e->instance->mirror;
 			bool mirror = e->instance->mirror;
@@ -1413,7 +1419,7 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren
 	RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
 	RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
 }
 }
 
 
-void RendererSceneRenderForward::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) {
+void RendererSceneRenderForward::_add_geometry(GeometryInstanceForward *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) {
 	RID m_src;
 	RID m_src;
 
 
 	m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
 	m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
@@ -1453,7 +1459,7 @@ void RendererSceneRenderForward::_add_geometry(InstanceBase *p_instance, uint32_
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) {
+void RendererSceneRenderForward::_add_geometry_with_material(GeometryInstanceForward *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) {
 	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_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 || has_read_screen_alpha);
 	bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
 	bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
 	bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
@@ -1476,7 +1482,7 @@ void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_ins
 	}
 	}
 
 
 	if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) {
 	if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) {
-		if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
+		if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) {
 			//conditions in which no depth pass should be processed
 			//conditions in which no depth pass should be processed
 			return;
 			return;
 		}
 		}
@@ -1521,8 +1527,8 @@ void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_ins
 	e->geometry_index = p_geometry_index;
 	e->geometry_index = p_geometry_index;
 	e->material_index = e->material->index;
 	e->material_index = e->material->index;
 	e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH;
 	e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH;
-	e->uses_lightmap = e->instance->lightmap != nullptr || !e->instance->lightmap_sh.is_empty();
-	e->uses_forward_gi = has_alpha && (e->instance->gi_probe_instances.size() || p_using_sdfgi);
+	e->uses_lightmap = e->instance->lightmap_instance.is_valid() || e->instance->lightmap_sh != nullptr;
+	e->uses_forward_gi = has_alpha && (e->instance->gi_probe_instance_count > 0 || p_using_sdfgi);
 	e->shader_index = e->shader_index;
 	e->shader_index = e->shader_index;
 	e->depth_layer = e->instance->depth_layer;
 	e->depth_layer = e->instance->depth_layer;
 	e->priority = p_material->priority;
 	e->priority = p_material->priority;
@@ -1532,7 +1538,7 @@ void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_ins
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi) {
+void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi) {
 	scene_state.current_shader_index = 0;
 	scene_state.current_shader_index = 0;
 	scene_state.current_material_index = 0;
 	scene_state.current_material_index = 0;
 	scene_state.used_sss = false;
 	scene_state.used_sss = false;
@@ -1549,7 +1555,7 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase
 	//fill list
 	//fill list
 
 
 	for (int i = 0; i < (int)p_instances.size(); i++) {
 	for (int i = 0; i < (int)p_instances.size(); i++) {
-		InstanceBase *inst = p_instances[i];
+		GeometryInstanceForward *inst = static_cast<GeometryInstanceForward *>(p_instances[i]);
 
 
 		inst->depth = near_plane.distance_to(inst->transform.origin);
 		inst->depth = near_plane.distance_to(inst->transform.origin);
 		inst->depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
 		inst->depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
@@ -1565,7 +1571,7 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase
 					continue; //nothing to do
 					continue; //nothing to do
 				}
 				}
 
 
-				const RID *inst_materials = inst->materials.ptr();
+				const RID *inst_materials = inst->surface_materials.ptr();
 
 
 				for (uint32_t j = 0; j < surface_count; j++) {
 				for (uint32_t j = 0; j < surface_count; j++) {
 					RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
 					RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
@@ -1642,26 +1648,29 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform) {
-	uint32_t lightmaps_used = 0;
+void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) {
+	scene_state.lightmaps_used = 0;
 	for (int i = 0; i < (int)p_lightmaps.size(); i++) {
 	for (int i = 0; i < (int)p_lightmaps.size(); i++) {
 		if (i >= (int)scene_state.max_lightmaps) {
 		if (i >= (int)scene_state.max_lightmaps) {
 			break;
 			break;
 		}
 		}
 
 
-		InstanceBase *lm = p_lightmaps[i];
-		Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis;
+		RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]);
+
+		Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
 		to_lm = to_lm.inverse().transposed(); //will transform normals
 		to_lm = to_lm.inverse().transposed(); //will transform normals
 		RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
 		RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
-		lm->lightmap_cull_index = i;
-		lightmaps_used++;
+		scene_state.lightmap_ids[i] = p_lightmaps[i];
+		scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap);
+
+		scene_state.lightmaps_used++;
 	}
 	}
-	if (lightmaps_used > 0) {
-		RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * lightmaps_used, scene_state.lightmaps, true);
+	if (scene_state.lightmaps_used > 0) {
+		RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps, true);
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
 	RenderBufferDataForward *render_buffer = nullptr;
 	RenderBufferDataForward *render_buffer = nullptr;
 	if (p_render_buffer.is_valid()) {
 	if (p_render_buffer.is_valid()) {
 		render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
 		render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
@@ -1885,7 +1894,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 	if (depth_pre_pass) { //depth pre pass
 	if (depth_pre_pass) { //depth pre pass
 		RENDER_TIMESTAMP("Render Depth Pre-Pass");
 		RENDER_TIMESTAMP("Render Depth Pre-Pass");
 
 
-		RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+		_setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
 
 
 		bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
 		bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
 		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
 		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
@@ -1917,7 +1926,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 
 
 	RENDER_TIMESTAMP("Render Opaque Pass");
 	RENDER_TIMESTAMP("Render Opaque Pass");
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes);
+	_setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes, p_lightmaps);
 
 
 	bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
 	bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
 	bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
 	bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
@@ -2036,7 +2045,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2057,7 +2066,7 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedAr
 
 
 	_fill_render_list(p_instances, pass_mode, p_projection, p_transform);
 	_fill_render_list(p_instances, pass_mode, p_projection, p_transform);
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
 
 
 	RENDER_TIMESTAMP("Render Shadow");
 	RENDER_TIMESTAMP("Render Shadow");
 
 
@@ -2073,7 +2082,7 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedAr
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
 	RENDER_TIMESTAMP("Setup Render Collider Heightfield");
 	RENDER_TIMESTAMP("Setup Render Collider Heightfield");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2090,7 +2099,7 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,
 
 
 	_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
 	_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
 
 
 	RENDER_TIMESTAMP("Render Collider Heightield");
 	RENDER_TIMESTAMP("Render Collider Heightield");
 
 
@@ -2106,7 +2115,7 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
 	RENDER_TIMESTAMP("Setup Rendering Material");
 	RENDER_TIMESTAMP("Setup Rendering Material");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2123,7 +2132,7 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
 	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
 	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
 	_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
 	_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
 
 
 	RENDER_TIMESTAMP("Render Material");
 	RENDER_TIMESTAMP("Render Material");
 
 
@@ -2145,7 +2154,7 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
 	RENDER_TIMESTAMP("Setup Rendering UV2");
 	RENDER_TIMESTAMP("Setup Rendering UV2");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2162,7 +2171,7 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p
 	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
 	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
 	_fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());
 	_fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());
 
 
-	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
 
 
 	RENDER_TIMESTAMP("Render Material");
 	RENDER_TIMESTAMP("Render Material");
 
 
@@ -2206,7 +2215,7 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
 	RENDER_TIMESTAMP("Render SDFGI");
 	RENDER_TIMESTAMP("Render SDFGI");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -2380,20 +2389,13 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
 			u.binding = 11;
 			u.binding = 11;
-			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
-			u.ids = storage->lightmap_array_get_textures();
-			uniforms.push_back(u);
-		}
-		{
-			RD::Uniform u;
-			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.ids.push_back(scene_state.lightmap_capture_buffer);
 			u.ids.push_back(scene_state.lightmap_capture_buffer);
 			uniforms.push_back(u);
 			uniforms.push_back(u);
 		}
 		}
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 13;
+			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID decal_atlas = storage->decal_atlas_get_texture();
 			RID decal_atlas = storage->decal_atlas_get_texture();
 			u.ids.push_back(decal_atlas);
 			u.ids.push_back(decal_atlas);
@@ -2401,7 +2403,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 		}
 		}
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 14;
+			u.binding = 13;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID decal_atlas = storage->decal_atlas_get_texture_srgb();
 			RID decal_atlas = storage->decal_atlas_get_texture_srgb();
 			u.ids.push_back(decal_atlas);
 			u.ids.push_back(decal_atlas);
@@ -2409,7 +2411,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 		}
 		}
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 15;
+			u.binding = 14;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.ids.push_back(get_decal_buffer());
 			u.ids.push_back(get_decal_buffer());
 			uniforms.push_back(u);
 			uniforms.push_back(u);
@@ -2417,14 +2419,14 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 
 
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 16;
+			u.binding = 15;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.ids.push_back(get_cluster_builder_texture());
 			u.ids.push_back(get_cluster_builder_texture());
 			uniforms.push_back(u);
 			uniforms.push_back(u);
 		}
 		}
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 17;
+			u.binding = 16;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.ids.push_back(get_cluster_builder_indices_buffer());
 			u.ids.push_back(get_cluster_builder_indices_buffer());
 			uniforms.push_back(u);
 			uniforms.push_back(u);
@@ -2432,7 +2434,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 
 
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 18;
+			u.binding = 17;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			if (directional_shadow_get_texture().is_valid()) {
 			if (directional_shadow_get_texture().is_valid()) {
 				u.ids.push_back(directional_shadow_get_texture());
 				u.ids.push_back(directional_shadow_get_texture());
@@ -2445,7 +2447,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
 			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-			u.binding = 19;
+			u.binding = 18;
 			u.ids.push_back(storage->global_variables_get_storage_buffer());
 			u.ids.push_back(storage->global_variables_get_storage_buffer());
 			uniforms.push_back(u);
 			uniforms.push_back(u);
 		}
 		}
@@ -2453,7 +2455,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 		if (!low_end) {
 		if (!low_end) {
 			RD::Uniform u;
 			RD::Uniform u;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-			u.binding = 20;
+			u.binding = 19;
 			u.ids.push_back(sdfgi_get_ubo());
 			u.ids.push_back(sdfgi_get_ubo());
 			uniforms.push_back(u);
 			uniforms.push_back(u);
 		}
 		}
@@ -2462,7 +2464,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
 	}
 	}
 }
 }
 
 
-RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes) {
+RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps) {
 	if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
 	if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
 		RD::get_singleton()->free(render_pass_uniform_set);
 		RD::get_singleton()->free(render_pass_uniform_set);
 	}
 	}
@@ -2517,11 +2519,29 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 		u.ids.push_back(texture);
 		u.ids.push_back(texture);
 		uniforms.push_back(u);
 		uniforms.push_back(u);
 	}
 	}
-
 	{
 	{
 		RD::Uniform u;
 		RD::Uniform u;
 		u.binding = 3;
 		u.binding = 3;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+		u.ids.resize(scene_state.max_lightmaps);
+		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
+			if (i < p_lightmaps.size()) {
+				RID base = lightmap_instance_get_lightmap(p_lightmaps[i]);
+				RID texture = storage->lightmap_get_texture(base);
+				RID rd_texture = storage->texture_get_rd_texture(texture);
+				u.ids.write[i] = rd_texture;
+			} else {
+				u.ids.write[i] = default_tex;
+			}
+		}
+
+		uniforms.push_back(u);
+	}
+	{
+		RD::Uniform u;
+		u.binding = 4;
+		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.ids.resize(MAX_GI_PROBES);
 		u.ids.resize(MAX_GI_PROBES);
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		for (int i = 0; i < MAX_GI_PROBES; i++) {
 		for (int i = 0; i < MAX_GI_PROBES; i++) {
@@ -2541,7 +2561,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 
 
 	{
 	{
 		RD::Uniform u;
 		RD::Uniform u;
-		u.binding = 4;
+		u.binding = 5;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
 		RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
 		u.ids.push_back(texture);
 		u.ids.push_back(texture);
@@ -2549,7 +2569,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 	}
 	}
 	{
 	{
 		RD::Uniform u;
 		RD::Uniform u;
-		u.binding = 5;
+		u.binding = 6;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_buffers) : RID();
 		RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_buffers) : RID();
 		RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
 		RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2559,7 +2579,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 	if (!low_end) {
 	if (!low_end) {
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 6;
+			u.binding = 7;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL);
 			RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL);
 			u.ids.push_back(texture);
 			u.ids.push_back(texture);
@@ -2568,7 +2588,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 
 
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 7;
+			u.binding = 8;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID aot = rb ? render_buffers_get_ao_texture(p_render_buffers) : RID();
 			RID aot = rb ? render_buffers_get_ao_texture(p_render_buffers) : RID();
 			RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
 			RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2578,7 +2598,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 
 
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 8;
+			u.binding = 9;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID texture = rb && rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
 			RID texture = rb && rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
 			u.ids.push_back(texture);
 			u.ids.push_back(texture);
@@ -2587,7 +2607,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 
 
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 9;
+			u.binding = 10;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID texture = rb && rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
 			RID texture = rb && rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
 			u.ids.push_back(texture);
 			u.ids.push_back(texture);
@@ -2595,7 +2615,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 		}
 		}
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 10;
+			u.binding = 11;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID t;
 			RID t;
 			if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
 			if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
@@ -2608,7 +2628,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 		}
 		}
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 11;
+			u.binding = 12;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
 			if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
 				u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers));
 				u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers));
@@ -2619,14 +2639,14 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
 		}
 		}
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 12;
+			u.binding = 13;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 			u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_buffers) : render_buffers_get_default_gi_probe_buffer());
 			u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_buffers) : render_buffers_get_default_gi_probe_buffer());
 			uniforms.push_back(u);
 			uniforms.push_back(u);
 		}
 		}
 		{
 		{
 			RD::Uniform u;
 			RD::Uniform u;
-			u.binding = 13;
+			u.binding = 14;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 			RID vfog = RID();
 			RID vfog = RID();
 			if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) {
 			if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) {
@@ -2684,10 +2704,24 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
 	}
 	}
 
 
 	{
 	{
-		// No GIProbes
+		// No Lightmaps
 		RD::Uniform u;
 		RD::Uniform u;
 		u.binding = 3;
 		u.binding = 3;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+		u.ids.resize(scene_state.max_lightmaps);
+		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
+			u.ids.write[i] = default_tex;
+		}
+
+		uniforms.push_back(u);
+	}
+
+	{
+		// No GIProbes
+		RD::Uniform u;
+		u.binding = 4;
+		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
 		u.ids.resize(MAX_GI_PROBES);
 		u.ids.resize(MAX_GI_PROBES);
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
 		for (int i = 0; i < MAX_GI_PROBES; i++) {
 		for (int i = 0; i < MAX_GI_PROBES; i++) {
@@ -2701,28 +2735,28 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
 	{
 	{
 		RD::Uniform u;
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-		u.binding = 4;
+		u.binding = 5;
 		u.ids.push_back(p_albedo_texture);
 		u.ids.push_back(p_albedo_texture);
 		uniforms.push_back(u);
 		uniforms.push_back(u);
 	}
 	}
 	{
 	{
 		RD::Uniform u;
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-		u.binding = 5;
+		u.binding = 6;
 		u.ids.push_back(p_emission_texture);
 		u.ids.push_back(p_emission_texture);
 		uniforms.push_back(u);
 		uniforms.push_back(u);
 	}
 	}
 	{
 	{
 		RD::Uniform u;
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-		u.binding = 6;
+		u.binding = 7;
 		u.ids.push_back(p_emission_aniso_texture);
 		u.ids.push_back(p_emission_aniso_texture);
 		uniforms.push_back(u);
 		uniforms.push_back(u);
 	}
 	}
 	{
 	{
 		RD::Uniform u;
 		RD::Uniform u;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
 		u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-		u.binding = 7;
+		u.binding = 8;
 		u.ids.push_back(p_geom_facing_texture);
 		u.ids.push_back(p_geom_facing_texture);
 		uniforms.push_back(u);
 		uniforms.push_back(u);
 	}
 	}
@@ -2765,6 +2799,140 @@ void RendererSceneRenderForward::set_time(double p_time, double p_step) {
 	RendererSceneRenderRD::set_time(p_time, p_step);
 	RendererSceneRenderRD::set_time(p_time, p_step);
 }
 }
 
 
+RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_instance_create(RID p_base) {
+	RS::InstanceType type = storage->get_base_type(p_base);
+	ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
+
+	GeometryInstanceForward *ginstance = geometry_instance_alloc.alloc();
+
+	ginstance->base = p_base;
+	ginstance->base_type = type;
+
+	return ginstance;
+}
+void RendererSceneRenderForward::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->skeleton = p_skeleton;
+}
+void RendererSceneRenderForward::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->material_override = p_override;
+}
+void RendererSceneRenderForward::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->surface_materials = p_materials;
+}
+void RendererSceneRenderForward::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->mesh_instance = p_mesh_instance;
+}
+void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->transform = p_transform;
+	ginstance->mirror = p_transform.basis.determinant() < 0;
+	ginstance->aabb = p_aabb;
+	ginstance->transformed_aabb = p_transformed_aabb;
+}
+void RendererSceneRenderForward::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->lod_bias = p_lod_bias;
+}
+void RendererSceneRenderForward::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->use_baked_light = p_enable;
+}
+void RendererSceneRenderForward::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->use_dynamic_gi = p_enable;
+}
+void RendererSceneRenderForward::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->lightmap_instance = p_lightmap_instance;
+	ginstance->lightmap_uv_scale = p_lightmap_uv_scale;
+	ginstance->lightmap_slice_index = p_lightmap_slice_index;
+}
+void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	if (p_sh9) {
+		if (ginstance->lightmap_sh == nullptr) {
+			ginstance->lightmap_sh = (Color *)memalloc(sizeof(Color) * 9);
+		}
+
+		copymem(ginstance->lightmap_sh, p_sh9, sizeof(Color) * 9);
+	} else {
+		if (ginstance->lightmap_sh != nullptr) {
+			memfree(ginstance->lightmap_sh);
+			ginstance->lightmap_sh = nullptr;
+		}
+	}
+}
+void RendererSceneRenderForward::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->shader_parameters_offset = p_offset;
+}
+void RendererSceneRenderForward::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+
+	ginstance->cast_double_sided_shaodows = p_enable;
+}
+
+void RendererSceneRenderForward::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->layer_mask = p_layer_mask;
+}
+
+void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	if (ginstance->lightmap_sh != nullptr) {
+		memfree(ginstance->lightmap_sh);
+	}
+	geometry_instance_alloc.free(ginstance);
+}
+
+uint32_t RendererSceneRenderForward::geometry_instance_get_pair_mask() {
+	return (1 << RS::INSTANCE_GI_PROBE);
+}
+void RendererSceneRenderForward::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
+}
+void RendererSceneRenderForward::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
+}
+void RendererSceneRenderForward::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
+}
+
+Transform RendererSceneRenderForward::geometry_instance_get_transform(GeometryInstance *p_instance) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance);
+	ERR_FAIL_COND_V(!ginstance, Transform());
+	return ginstance->transform;
+}
+AABB RendererSceneRenderForward::geometry_instance_get_aabb(GeometryInstance *p_instance) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance);
+	ERR_FAIL_COND_V(!ginstance, AABB());
+	return ginstance->aabb;
+}
+
+void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) {
+	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+	ERR_FAIL_COND(!ginstance);
+	ginstance->gi_probe_instance_count = MIN(p_gi_probe_instance_count, MAX_GI_PROBES);
+	for (uint32_t i = 0; i < ginstance->gi_probe_instance_count; i++) {
+		ginstance->gi_probe_instances[i] = p_gi_probe_instances[i];
+	}
+}
+
 RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) :
 RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) :
 		RendererSceneRenderRD(p_storage) {
 		RendererSceneRenderRD(p_storage) {
 	singleton = this;
 	singleton = this;
@@ -2788,11 +2956,10 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
 
 
 		{
 		{
 			//lightmaps
 			//lightmaps
-			scene_state.max_lightmaps = storage->lightmap_array_get_size();
+			scene_state.max_lightmaps = low_end ? 2 : MAX_LIGHTMAPS;
 			defines += "\n#define MAX_LIGHTMAP_TEXTURES " + itos(scene_state.max_lightmaps) + "\n";
 			defines += "\n#define MAX_LIGHTMAP_TEXTURES " + itos(scene_state.max_lightmaps) + "\n";
 			defines += "\n#define MAX_LIGHTMAPS " + itos(scene_state.max_lightmaps) + "\n";
 			defines += "\n#define MAX_LIGHTMAPS " + itos(scene_state.max_lightmaps) + "\n";
 
 
-			scene_state.lightmaps = memnew_arr(LightmapData, scene_state.max_lightmaps);
 			scene_state.lightmap_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapData) * scene_state.max_lightmaps);
 			scene_state.lightmap_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapData) * scene_state.max_lightmaps);
 		}
 		}
 		{
 		{
@@ -3099,7 +3266,6 @@ RendererSceneRenderForward::~RendererSceneRenderForward() {
 		RD::get_singleton()->free(scene_state.lightmap_buffer);
 		RD::get_singleton()->free(scene_state.lightmap_buffer);
 		RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
 		RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
 		memdelete_arr(scene_state.instances);
 		memdelete_arr(scene_state.instances);
-		memdelete_arr(scene_state.lightmaps);
 		memdelete_arr(scene_state.lightmap_captures);
 		memdelete_arr(scene_state.lightmap_captures);
 	}
 	}
 
 

+ 82 - 14
servers/rendering/renderer_rd/renderer_scene_render_forward.h

@@ -31,6 +31,7 @@
 #ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_H
 #ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_H
 #define RENDERING_SERVER_SCENE_RENDER_FORWARD_H
 #define RENDERING_SERVER_SCENE_RENDER_FORWARD_H
 
 
+#include "core/templates/paged_allocator.h"
 #include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
 #include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
 #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
 #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
 #include "servers/rendering/renderer_rd/renderer_storage_rd.h"
 #include "servers/rendering/renderer_rd/renderer_storage_rd.h"
@@ -46,7 +47,8 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
 
 
 	enum {
 	enum {
 		SDFGI_MAX_CASCADES = 8,
 		SDFGI_MAX_CASCADES = 8,
-		MAX_GI_PROBES = 8
+		MAX_GI_PROBES = 8,
+		MAX_LIGHTMAPS = 8
 	};
 	};
 
 
 	/* Scene Shader */
 	/* Scene Shader */
@@ -266,7 +268,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
 
 
 	void _update_render_base_uniform_set();
 	void _update_render_base_uniform_set();
 	RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
 	RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
-	RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes);
+	RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps);
 
 
 	struct LightmapData {
 	struct LightmapData {
 		float normal_xform[12];
 		float normal_xform[12];
@@ -385,7 +387,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
 
 
 		RID uniform_buffer;
 		RID uniform_buffer;
 
 
-		LightmapData *lightmaps;
+		LightmapData lightmaps[MAX_LIGHTMAPS];
+		RID lightmap_ids[MAX_LIGHTMAPS];
+		bool lightmap_has_sh[MAX_LIGHTMAPS];
+		uint32_t lightmaps_used = 0;
 		uint32_t max_lightmaps;
 		uint32_t max_lightmaps;
 		RID lightmap_buffer;
 		RID lightmap_buffer;
 
 
@@ -408,11 +413,13 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
 
 
 	/* Render List */
 	/* Render List */
 
 
+	struct GeometryInstanceForward;
+
 	struct RenderList {
 	struct RenderList {
 		int max_elements;
 		int max_elements;
 
 
 		struct Element {
 		struct Element {
-			RendererSceneRender::InstanceBase *instance;
+			GeometryInstanceForward *instance;
 			MaterialData *material;
 			MaterialData *material;
 			union {
 			union {
 				struct {
 				struct {
@@ -567,28 +574,89 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
 	};
 	};
 
 
 	void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
 	void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
-	void _setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform);
+	void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform);
 
 
 	void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
 	void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
 	void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
 	void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
-	_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
-	_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
+	_FORCE_INLINE_ void _add_geometry(GeometryInstanceForward *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
+	_FORCE_INLINE_ void _add_geometry_with_material(GeometryInstanceForward *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
 
 
-	void _fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false);
+	void _fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false);
 
 
 	Map<Size2i, RID> sdfgi_framebuffer_size_cache;
 	Map<Size2i, RID> sdfgi_framebuffer_size_cache;
 
 
+	struct GeometryInstanceForward : public GeometryInstance {
+		RID base;
+		RS::InstanceType base_type;
+
+		RID skeleton;
+		RID mesh_instance;
+
+		uint32_t layer_mask = 1;
+
+		float depth = 0;
+		int depth_layer = 0;
+
+		RID gi_probe_instances[MAX_GI_PROBES];
+		uint32_t gi_probe_instance_count = 0;
+
+		Vector<RID> surface_materials;
+		RID material_override;
+		Transform transform;
+		AABB aabb;
+		AABB transformed_aabb;
+		float lod_bias = 0.0;
+		int32_t shader_parameters_offset = -1;
+
+		bool use_dynamic_gi = false;
+		bool use_baked_light = false;
+		bool cast_double_sided_shaodows = false;
+		bool mirror = false;
+		RID lightmap_instance;
+		Rect2 lightmap_uv_scale;
+		uint32_t lightmap_slice_index = 0;
+		Color *lightmap_sh = nullptr;
+	};
+
+	PagedAllocator<GeometryInstanceForward> geometry_instance_alloc;
+
 	bool low_end = false;
 	bool low_end = false;
 
 
 protected:
 protected:
-	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
-	virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
-	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
-	virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
-	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
-	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances);
+	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
+	virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
+	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+	virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
+	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
 
 
 public:
 public:
+	virtual GeometryInstance *geometry_instance_create(RID p_base);
+	virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton);
+	virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
+	virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
+	virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
+	virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
+	virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
+	virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
+	virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
+	virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable);
+	virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index);
+	virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9);
+	virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
+	virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
+
+	virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance);
+	virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
+
+	virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
+
+	virtual uint32_t geometry_instance_get_pair_mask();
+	virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
+	virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
+	virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
+	virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count);
+
 	virtual void set_time(double p_time, double p_step);
 	virtual void set_time(double p_time, double p_step);
 
 
 	virtual bool free(RID p_rid);
 	virtual bool free(RID p_rid);

+ 36 - 19
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -4035,6 +4035,19 @@ void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Tran
 
 
 /////////////////////////////////
 /////////////////////////////////
 
 
+RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) {
+	LightmapInstance li;
+	li.lightmap = p_lightmap;
+	return lightmap_instance_owner.make_rid(li);
+}
+void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) {
+	LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap);
+	ERR_FAIL_COND(!li);
+	li->transform = p_transform;
+}
+
+/////////////////////////////////
+
 RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) {
 RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) {
 	GIProbeInstance gi_probe;
 	GIProbeInstance gi_probe;
 	gi_probe.probe = p_base;
 	gi_probe.probe = p_base;
@@ -4061,7 +4074,7 @@ bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {
 	return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
 	return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
 }
 }
 
 
-void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<InstanceBase *> &p_dynamic_objects) {
+void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
 	GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
 	GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
 	ERR_FAIL_COND(!gi_probe);
 	ERR_FAIL_COND(!gi_probe);
 
 
@@ -4578,13 +4591,10 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
 
 
 		//this could probably be better parallelized in compute..
 		//this could probably be better parallelized in compute..
 		for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
 		for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
-			InstanceBase *instance = p_dynamic_objects[i];
-			//not used, so clear
-			instance->depth_layer = 0;
-			instance->depth = 0;
+			GeometryInstance *instance = p_dynamic_objects[i];
 
 
 			//transform aabb to giprobe
 			//transform aabb to giprobe
-			AABB aabb = (to_probe_xform * instance->transform).xform(instance->aabb);
+			AABB aabb = (to_probe_xform * geometry_instance_get_transform(instance)).xform(geometry_instance_get_aabb(instance));
 
 
 			//this needs to wrap to grid resolution to avoid jitter
 			//this needs to wrap to grid resolution to avoid jitter
 			//also extend margin a bit just in case
 			//also extend margin a bit just in case
@@ -7101,7 +7111,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 	RD::get_singleton()->compute_list_end();
 	RD::get_singleton()->compute_list_end();
 }
 }
 
 
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
 	Color clear_color;
 	Color clear_color;
 	if (p_render_buffers.is_valid()) {
 	if (p_render_buffers.is_valid()) {
 		RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 		RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -7177,7 +7187,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
 	LightInstance *light_instance = light_instance_owner.getornull(p_light);
 	LightInstance *light_instance = light_instance_owner.getornull(p_light);
 	ERR_FAIL_COND(!light_instance);
 	ERR_FAIL_COND(!light_instance);
 
 
@@ -7353,11 +7363,11 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
 	_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);
 	_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);
 }
 }
 
 
-void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) {
 	//print_line("rendering region " + itos(p_region));
 	//print_line("rendering region " + itos(p_region));
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
 	ERR_FAIL_COND(!rb);
 	ERR_FAIL_COND(!rb);
@@ -7694,7 +7704,7 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, con
 	}
 	}
 }
 }
 
 
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
 	ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
 	ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
 	Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
 	Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
 	CameraMatrix cm;
 	CameraMatrix cm;
@@ -7844,6 +7854,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
 		reflection_probe_instance_owner.free(p_rid);
 		reflection_probe_instance_owner.free(p_rid);
 	} else if (decal_instance_owner.owns(p_rid)) {
 	} else if (decal_instance_owner.owns(p_rid)) {
 		decal_instance_owner.free(p_rid);
 		decal_instance_owner.free(p_rid);
+	} else if (lightmap_instance_owner.owns(p_rid)) {
+		lightmap_instance_owner.free(p_rid);
 	} else if (gi_probe_instance_owner.owns(p_rid)) {
 	} else if (gi_probe_instance_owner.owns(p_rid)) {
 		GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
 		GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
 		if (gi_probe->texture.is_valid()) {
 		if (gi_probe->texture.is_valid()) {
@@ -7979,23 +7991,28 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
 
 
 	//RID sampled_light;
 	//RID sampled_light;
 
 
-	InstanceBase ins;
+	GeometryInstance *gi = geometry_instance_create(p_base);
+
+	uint32_t sc = RSG::storage->mesh_get_surface_count(p_base);
+	Vector<RID> materials;
+	materials.resize(sc);
 
 
-	ins.base_type = RSG::storage->get_base_type(p_base);
-	ins.base = p_base;
-	ins.materials.resize(RSG::storage->mesh_get_surface_count(p_base));
-	for (int i = 0; i < ins.materials.size(); i++) {
-		if (i < p_material_overrides.size()) {
-			ins.materials.write[i] = p_material_overrides[i];
+	for (uint32_t i = 0; i < sc; i++) {
+		if (i < (uint32_t)p_material_overrides.size()) {
+			materials.write[i] = p_material_overrides[i];
 		}
 		}
 	}
 	}
 
 
+	geometry_instance_set_surface_materials(gi, materials);
+
 	if (cull_argument.size() == 0) {
 	if (cull_argument.size() == 0) {
 		cull_argument.push_back(nullptr);
 		cull_argument.push_back(nullptr);
 	}
 	}
-	cull_argument[0] = &ins;
+	cull_argument[0] = gi;
 	_render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
 	_render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
 
 
+	geometry_instance_free(gi);
+
 	TypedArray<Image> ret;
 	TypedArray<Image> ret;
 
 
 	{
 	{

+ 37 - 14
servers/rendering/renderer_rd/renderer_scene_render_rd.h

@@ -109,12 +109,12 @@ protected:
 	void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);
 	void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);
 	void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used);
 	void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used);
 
 
-	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
-	virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
-	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
-	virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
-	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
-	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) = 0;
+	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
+	virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
+	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+	virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
+	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
 
 
 	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
 	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
 	void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
 	void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
@@ -137,8 +137,8 @@ protected:
 	void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);
 	void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);
 
 
 	// needed for a single argument calls (material and uv2)
 	// needed for a single argument calls (material and uv2)
-	PagedArrayPool<InstanceBase *> cull_argument_pool;
-	PagedArray<InstanceBase *> cull_argument; //need this to exist
+	PagedArrayPool<GeometryInstance *> cull_argument_pool;
+	PagedArray<GeometryInstance *> cull_argument; //need this to exist
 private:
 private:
 	RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
 	RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
 	double time_step = 0;
 	double time_step = 0;
@@ -374,6 +374,15 @@ private:
 
 
 	mutable RID_Owner<DecalInstance> decal_instance_owner;
 	mutable RID_Owner<DecalInstance> decal_instance_owner;
 
 
+	/* LIGHTMAP INSTANCE */
+
+	struct LightmapInstance {
+		RID lightmap;
+		Transform transform;
+	};
+
+	mutable RID_Owner<LightmapInstance> lightmap_instance_owner;
+
 	/* GIPROBE INSTANCE */
 	/* GIPROBE INSTANCE */
 
 
 	struct GIProbeLight {
 	struct GIProbeLight {
@@ -1473,6 +1482,9 @@ private:
 	bool low_end = false;
 	bool low_end = false;
 
 
 public:
 public:
+	virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
+	virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0;
+
 	/* SHADOW ATLAS API */
 	/* SHADOW ATLAS API */
 
 
 	RID shadow_atlas_create();
 	RID shadow_atlas_create();
@@ -1822,10 +1834,21 @@ public:
 		return decal->transform;
 		return decal->transform;
 	}
 	}
 
 
+	virtual RID lightmap_instance_create(RID p_lightmap);
+	virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform);
+	_FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) {
+		LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
+		return li->lightmap;
+	}
+	_FORCE_INLINE_ Transform lightmap_instance_get_transform(RID p_lightmap_instance) {
+		LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
+		return li->transform;
+	}
+
 	RID gi_probe_instance_create(RID p_base);
 	RID gi_probe_instance_create(RID p_base);
 	void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
 	void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
 	bool gi_probe_needs_update(RID p_probe) const;
 	bool gi_probe_needs_update(RID p_probe) const;
-	void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects);
+	void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);
 
 
 	void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
 	void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
 
 
@@ -1900,16 +1923,16 @@ public:
 	float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
 	float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
 	float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
 	float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
 
 
-	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
+	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
 
 
-	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
+	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
 
 
-	void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+	void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
 
 
-	void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances);
+	void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances);
 	void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);
 	void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);
 
 
-	void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances);
+	void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances);
 
 
 	virtual void set_scene_pass(uint64_t p_pass) {
 	virtual void set_scene_pass(uint64_t p_pass) {
 		scene_pass = p_pass;
 		scene_pass = p_pass;

+ 36 - 15
servers/rendering/renderer_rd/renderer_storage_rd.cpp

@@ -4155,24 +4155,18 @@ RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass)
 	return particles->draw_passes[p_pass];
 	return particles->draw_passes[p_pass];
 }
 }
 
 
-void RendererStorageRD::particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance) {
-	RendererSceneRender::InstanceBase *instance = static_cast<RendererSceneRender::InstanceBase *>(p_instance);
-
+void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
 	Particles *particles = particles_owner.getornull(p_particles);
 	Particles *particles = particles_owner.getornull(p_particles);
 	ERR_FAIL_COND(!particles);
 	ERR_FAIL_COND(!particles);
 
 
-	ERR_FAIL_COND(instance->base_type != RS::INSTANCE_PARTICLES_COLLISION);
-
-	particles->collisions.insert(instance);
+	particles->collisions.insert(p_particles_collision_instance);
 }
 }
 
 
-void RendererStorageRD::particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance) {
-	RendererSceneRender::InstanceBase *instance = static_cast<RendererSceneRender::InstanceBase *>(p_instance);
-
+void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
 	Particles *particles = particles_owner.getornull(p_particles);
 	Particles *particles = particles_owner.getornull(p_particles);
 	ERR_FAIL_COND(!particles);
 	ERR_FAIL_COND(!particles);
 
 
-	particles->collisions.erase(instance);
+	particles->collisions.erase(p_particles_collision_instance);
 }
 }
 
 
 void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) {
 void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) {
@@ -4272,9 +4266,15 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
 			to_particles = p_particles->emission_transform.affine_inverse();
 			to_particles = p_particles->emission_transform.affine_inverse();
 		}
 		}
 		uint32_t collision_3d_textures_used = 0;
 		uint32_t collision_3d_textures_used = 0;
-		for (const Set<RendererSceneRender::InstanceBase *>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
-			ParticlesCollision *pc = particles_collision_owner.getornull(E->get()->base);
-			Transform to_collider = E->get()->transform;
+		for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
+			ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(E->get());
+			if (!pci || !pci->active) {
+				continue;
+			}
+			ParticlesCollision *pc = particles_collision_owner.getornull(pci->collision);
+			ERR_CONTINUE(!pc);
+
+			Transform to_collider = pci->transform;
 			if (p_particles->use_local_coords) {
 			if (p_particles->use_local_coords) {
 				to_collider = to_particles * to_collider;
 				to_collider = to_particles * to_collider;
 			}
 			}
@@ -5096,6 +5096,22 @@ bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_colli
 	return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
 	return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
 }
 }
 
 
+RID RendererStorageRD::particles_collision_instance_create(RID p_collision) {
+	ParticlesCollisionInstance pci;
+	pci.collision = p_collision;
+	return particles_collision_instance_owner.make_rid(pci);
+}
+void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) {
+	ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
+	ERR_FAIL_COND(!pci);
+	pci->transform = p_transform;
+}
+void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+	ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
+	ERR_FAIL_COND(!pci);
+	pci->active = p_active;
+}
+
 /* SKELETON API */
 /* SKELETON API */
 
 
 RID RendererStorageRD::skeleton_create() {
 RID RendererStorageRD::skeleton_create() {
@@ -5290,17 +5306,20 @@ RID RendererStorageRD::light_create(RS::LightType p_type) {
 	light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
 	light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
 	light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
 	light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
 	light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
 	light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
+	light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0;
 	light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
 	light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
+	light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0;
 	light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
 	light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
 	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
 	light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
 	light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
-	light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
 	light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
 	light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+	light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+	light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
 	light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
 	light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
-	light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
 	light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 1.0;
 	light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 1.0;
+	light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
 
 
 	return light_owner.make_rid(light);
 	return light_owner.make_rid(light);
 }
 }
@@ -8188,6 +8207,8 @@ bool RendererStorageRD::free(RID p_rid) {
 		}
 		}
 		particles_collision->instance_dependency.instance_notify_deleted(p_rid);
 		particles_collision->instance_dependency.instance_notify_deleted(p_rid);
 		particles_collision_owner.free(p_rid);
 		particles_collision_owner.free(p_rid);
+	} else if (particles_collision_instance_owner.owns(p_rid)) {
+		particles_collision_instance_owner.free(p_rid);
 	} else if (render_target_owner.owns(p_rid)) {
 	} else if (render_target_owner.owns(p_rid)) {
 		RenderTarget *rt = render_target_owner.getornull(p_rid);
 		RenderTarget *rt = render_target_owner.getornull(p_rid);
 
 

+ 21 - 4
servers/rendering/renderer_rd/renderer_storage_rd.h

@@ -734,7 +734,7 @@ private:
 		ParticleEmissionBuffer *emission_buffer = nullptr;
 		ParticleEmissionBuffer *emission_buffer = nullptr;
 		RID emission_storage_buffer;
 		RID emission_storage_buffer;
 
 
-		Set<RendererSceneRender::InstanceBase *> collisions;
+		Set<RID> collisions;
 
 
 		Particles() :
 		Particles() :
 				inactive(true),
 				inactive(true),
@@ -894,6 +894,14 @@ private:
 
 
 	mutable RID_Owner<ParticlesCollision> particles_collision_owner;
 	mutable RID_Owner<ParticlesCollision> particles_collision_owner;
 
 
+	struct ParticlesCollisionInstance {
+		RID collision;
+		Transform transform;
+		bool active = false;
+	};
+
+	mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+
 	/* Skeleton */
 	/* Skeleton */
 
 
 	struct Skeleton {
 	struct Skeleton {
@@ -1977,7 +1985,11 @@ public:
 	_FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const {
 	_FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const {
 		return lightmap_probe_capture_update_speed;
 		return lightmap_probe_capture_update_speed;
 	}
 	}
-
+	_FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
+		const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+		ERR_FAIL_COND_V(!lm, RID());
+		return lm->light_texture;
+	}
 	_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
 	_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
 		ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
 		ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
 		const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
 		const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
@@ -2078,8 +2090,8 @@ public:
 		return particles->particles_transforms_buffer_uniform_set;
 		return particles->particles_transforms_buffer_uniform_set;
 	}
 	}
 
 
-	virtual void particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance);
-	virtual void particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance);
+	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance);
+	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance);
 
 
 	/* PARTICLES COLLISION */
 	/* PARTICLES COLLISION */
 
 
@@ -2099,6 +2111,11 @@ public:
 	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
 	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
 	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
 	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
 
 
+	//used from 2D and 3D
+	virtual RID particles_collision_instance_create(RID p_collision);
+	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform);
+	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
+
 	/* GLOBAL VARIABLES API */
 	/* GLOBAL VARIABLES API */
 
 
 	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);
 	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);

+ 26 - 26
servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl

@@ -177,35 +177,33 @@ layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps {
 }
 }
 lightmaps;
 lightmaps;
 
 
-layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
-
 struct LightmapCapture {
 struct LightmapCapture {
 	vec4 sh[9];
 	vec4 sh[9];
 };
 };
 
 
-layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures {
+layout(set = 0, binding = 11, std140) restrict readonly buffer LightmapCaptures {
 	LightmapCapture data[];
 	LightmapCapture data[];
 }
 }
 lightmap_captures;
 lightmap_captures;
 
 
-layout(set = 0, binding = 13) uniform texture2D decal_atlas;
-layout(set = 0, binding = 14) uniform texture2D decal_atlas_srgb;
+layout(set = 0, binding = 12) uniform texture2D decal_atlas;
+layout(set = 0, binding = 13) uniform texture2D decal_atlas_srgb;
 
 
-layout(set = 0, binding = 15, std430) restrict readonly buffer Decals {
+layout(set = 0, binding = 14, std430) restrict readonly buffer Decals {
 	DecalData data[];
 	DecalData data[];
 }
 }
 decals;
 decals;
 
 
-layout(set = 0, binding = 16) uniform utexture3D cluster_texture;
+layout(set = 0, binding = 15) uniform utexture3D cluster_texture;
 
 
-layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData {
+layout(set = 0, binding = 16, std430) restrict readonly buffer ClusterData {
 	uint indices[];
 	uint indices[];
 }
 }
 cluster_data;
 cluster_data;
 
 
-layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas;
+layout(set = 0, binding = 17) uniform texture2D directional_shadow_atlas;
 
 
-layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 18, std430) restrict readonly buffer GlobalVariableData {
 	vec4 data[];
 	vec4 data[];
 }
 }
 global_variables;
 global_variables;
@@ -219,7 +217,7 @@ struct SDFGIProbeCascadeData {
 	float to_cell; // 1/bounds * grid_size
 	float to_cell; // 1/bounds * grid_size
 };
 };
 
 
-layout(set = 0, binding = 20, std140) uniform SDFGI {
+layout(set = 0, binding = 19, std140) uniform SDFGI {
 	vec3 grid_size;
 	vec3 grid_size;
 	uint max_cascades;
 	uint max_cascades;
 
 
@@ -269,18 +267,20 @@ layout(set = 1, binding = 1) uniform textureCubeArray reflection_atlas;
 
 
 layout(set = 1, binding = 2) uniform texture2D shadow_atlas;
 layout(set = 1, binding = 2) uniform texture2D shadow_atlas;
 
 
+layout(set = 1, binding = 3) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+
 #ifndef LOW_END_MODE
 #ifndef LOW_END_MODE
-layout(set = 1, binding = 3) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
+layout(set = 1, binding = 4) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
 #endif
 #endif
 
 
 /* Set 3, Render Buffers */
 /* Set 3, Render Buffers */
 
 
 #ifdef MODE_RENDER_SDF
 #ifdef MODE_RENDER_SDF
 
 
-layout(r16ui, set = 1, binding = 4) uniform restrict writeonly uimage3D albedo_volume_grid;
-layout(r32ui, set = 1, binding = 5) uniform restrict writeonly uimage3D emission_grid;
-layout(r32ui, set = 1, binding = 6) uniform restrict writeonly uimage3D emission_aniso_grid;
-layout(r32ui, set = 1, binding = 7) uniform restrict uimage3D geom_facing_grid;
+layout(r16ui, set = 1, binding = 5) uniform restrict writeonly uimage3D albedo_volume_grid;
+layout(r32ui, set = 1, binding = 6) uniform restrict writeonly uimage3D emission_grid;
+layout(r32ui, set = 1, binding = 7) uniform restrict writeonly uimage3D emission_aniso_grid;
+layout(r32ui, set = 1, binding = 8) uniform restrict uimage3D geom_facing_grid;
 
 
 //still need to be present for shaders that use it, so remap them to something
 //still need to be present for shaders that use it, so remap them to something
 #define depth_buffer shadow_atlas
 #define depth_buffer shadow_atlas
@@ -289,17 +289,17 @@ layout(r32ui, set = 1, binding = 7) uniform restrict uimage3D geom_facing_grid;
 
 
 #else
 #else
 
 
-layout(set = 1, binding = 4) uniform texture2D depth_buffer;
-layout(set = 1, binding = 5) uniform texture2D color_buffer;
+layout(set = 1, binding = 5) uniform texture2D depth_buffer;
+layout(set = 1, binding = 6) uniform texture2D color_buffer;
 
 
 #ifndef LOW_END_MODE
 #ifndef LOW_END_MODE
 
 
-layout(set = 1, binding = 6) uniform texture2D normal_roughness_buffer;
-layout(set = 1, binding = 7) uniform texture2D ao_buffer;
-layout(set = 1, binding = 8) uniform texture2D ambient_buffer;
-layout(set = 1, binding = 9) uniform texture2D reflection_buffer;
-layout(set = 1, binding = 10) uniform texture2DArray sdfgi_lightprobe_texture;
-layout(set = 1, binding = 11) uniform texture3D sdfgi_occlusion_cascades;
+layout(set = 1, binding = 7) uniform texture2D normal_roughness_buffer;
+layout(set = 1, binding = 8) uniform texture2D ao_buffer;
+layout(set = 1, binding = 9) uniform texture2D ambient_buffer;
+layout(set = 1, binding = 10) uniform texture2D reflection_buffer;
+layout(set = 1, binding = 11) uniform texture2DArray sdfgi_lightprobe_texture;
+layout(set = 1, binding = 12) uniform texture3D sdfgi_occlusion_cascades;
 
 
 struct GIProbeData {
 struct GIProbeData {
 	mat4 xform;
 	mat4 xform;
@@ -317,12 +317,12 @@ struct GIProbeData {
 	uint mipmaps;
 	uint mipmaps;
 };
 };
 
 
-layout(set = 1, binding = 12, std140) uniform GIProbes {
+layout(set = 1, binding = 13, std140) uniform GIProbes {
 	GIProbeData data[MAX_GI_PROBES];
 	GIProbeData data[MAX_GI_PROBES];
 }
 }
 gi_probes;
 gi_probes;
 
 
-layout(set = 1, binding = 13) uniform texture3D volumetric_fog_texture;
+layout(set = 1, binding = 14) uniform texture3D volumetric_fog_texture;
 
 
 #endif // LOW_END_MODE
 #endif // LOW_END_MODE
 
 

+ 237 - 110
servers/rendering/renderer_scene_cull.cpp

@@ -135,7 +135,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
 			idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
 			idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
 		}
 		}
 
 
-	} else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+	} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
 		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
 		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 
 
@@ -147,7 +147,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
 			idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;
 			idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;
 		}
 		}
 
 
-	} else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+	} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
 		InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
 		InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 
 
@@ -174,7 +174,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
 			((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
 			((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
 		}
 		}
 
 
-	} else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+	} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 
 
@@ -195,7 +195,8 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
 		gi_probe->lights.insert(A);
 		gi_probe->lights.insert(A);
 	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
 	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
-		RSG::storage->particles_add_collision(A->base, B);
+		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
+		RSG::storage->particles_add_collision(A->base, collision->instance);
 	}
 	}
 }
 }
 
 
@@ -225,7 +226,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
 			idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
 			idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
 		}
 		}
 
 
-	} else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+	} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
 		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
 		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 
 
@@ -237,7 +238,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
 			idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;
 			idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;
 		}
 		}
 
 
-	} else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+	} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
 		InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
 		InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 
 
@@ -264,7 +265,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
 			((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
 			((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
 		}
 		}
 
 
-	} else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+	} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
 
 
@@ -284,7 +285,8 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
 		gi_probe->lights.erase(A);
 		gi_probe->lights.erase(A);
 	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
 	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
-		RSG::storage->particles_remove_collision(A->base, B);
+		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
+		RSG::storage->particles_remove_collision(A->base, collision->instance);
 	}
 	}
 }
 }
 
 
@@ -386,6 +388,9 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
 			p_instance->mesh_instance = RID();
 			p_instance->mesh_instance = RID();
 		}
 		}
 
 
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+		scene_render->geometry_instance_set_mesh_instance(geom->geometry_instance, p_instance->mesh_instance);
+
 		if (p_instance->scenario && p_instance->array_index >= 0) {
 		if (p_instance->scenario && p_instance->array_index >= 0) {
 			InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
 			InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
 			if (p_instance->mesh_instance.is_valid()) {
 			if (p_instance->mesh_instance.is_valid()) {
@@ -421,6 +426,13 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
 		}
 		}
 
 
 		switch (instance->base_type) {
 		switch (instance->base_type) {
+			case RS::INSTANCE_MESH:
+			case RS::INSTANCE_MULTIMESH:
+			case RS::INSTANCE_IMMEDIATE:
+			case RS::INSTANCE_PARTICLES: {
+				InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+				scene_render->geometry_instance_free(geom->geometry_instance);
+			} break;
 			case RS::INSTANCE_LIGHT: {
 			case RS::INSTANCE_LIGHT: {
 				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
 				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
 
 
@@ -439,6 +451,10 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
 				}
 				}
 				scene_render->free(light->instance);
 				scene_render->free(light->instance);
 			} break;
 			} break;
+			case RS::INSTANCE_PARTICLES_COLLISION: {
+				InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
+				RSG::storage->free(collision->instance);
+			} break;
 			case RS::INSTANCE_REFLECTION_PROBE: {
 			case RS::INSTANCE_REFLECTION_PROBE: {
 				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
 				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
 				scene_render->free(reflection_probe->instance);
 				scene_render->free(reflection_probe->instance);
@@ -457,6 +473,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
 				while (lightmap_data->users.front()) {
 				while (lightmap_data->users.front()) {
 					instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0);
 					instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0);
 				}
 				}
+				scene_render->free(lightmap_data->instance);
 			} break;
 			} break;
 			case RS::INSTANCE_GI_PROBE: {
 			case RS::INSTANCE_GI_PROBE: {
 				InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
 				InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
@@ -514,8 +531,29 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
 			case RS::INSTANCE_PARTICLES: {
 			case RS::INSTANCE_PARTICLES: {
 				InstanceGeometryData *geom = memnew(InstanceGeometryData);
 				InstanceGeometryData *geom = memnew(InstanceGeometryData);
 				instance->base_data = geom;
 				instance->base_data = geom;
+				geom->geometry_instance = scene_render->geometry_instance_create(p_base);
+
+				scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton);
+				scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override);
+				scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials);
+				scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb);
+				scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask);
+				scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, instance->lod_bias);
+				scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, instance->baked_light);
+				scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi);
+				scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
+				scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
+				if (instance->lightmap_sh.size() == 9) {
+					scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
+				}
 
 
 			} break;
 			} break;
+			case RS::INSTANCE_PARTICLES_COLLISION: {
+				InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData);
+				collision->instance = RSG::storage->particles_collision_instance_create(p_base);
+				RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
+				instance->base_data = collision;
+			} break;
 			case RS::INSTANCE_REFLECTION_PROBE: {
 			case RS::INSTANCE_REFLECTION_PROBE: {
 				InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
 				InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
 				reflection_probe->owner = instance;
 				reflection_probe->owner = instance;
@@ -533,7 +571,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
 			case RS::INSTANCE_LIGHTMAP: {
 			case RS::INSTANCE_LIGHTMAP: {
 				InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
 				InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
 				instance->base_data = lightmap_data;
 				instance->base_data = lightmap_data;
-				//lightmap_data->instance = scene_render->lightmap_data_instance_create(p_base);
+				lightmap_data->instance = scene_render->lightmap_instance_create(p_base);
 			} break;
 			} break;
 			case RS::INSTANCE_GI_PROBE: {
 			case RS::INSTANCE_GI_PROBE: {
 				InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData);
 				InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData);
@@ -659,6 +697,11 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
 	if (instance->scenario && instance->array_index >= 0) {
 	if (instance->scenario && instance->array_index >= 0) {
 		instance->scenario->instance_data[instance->array_index].layer_mask = p_mask;
 		instance->scenario->instance_data[instance->array_index].layer_mask = p_mask;
 	}
 	}
+
+	if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+		scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, p_mask);
+	}
 }
 }
 
 
 void RendererSceneCull::instance_set_transform(RID p_instance, const Transform &p_transform) {
 void RendererSceneCull::instance_set_transform(RID p_instance, const Transform &p_transform) {
@@ -739,6 +782,11 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
 	} else if (instance->indexer_id.is_valid()) {
 	} else if (instance->indexer_id.is_valid()) {
 		_unpair_instance(instance);
 		_unpair_instance(instance);
 	}
 	}
+
+	if (instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
+		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
+		RSG::storage->particles_collision_instance_set_active(collision->instance, p_visible);
+	}
 }
 }
 
 
 inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
 inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
@@ -785,9 +833,14 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
 		RSG::storage->skeleton_update_dependency(p_skeleton, instance);
 		RSG::storage->skeleton_update_dependency(p_skeleton, instance);
 	}
 	}
 
 
-	_instance_update_mesh_instance(instance);
-
 	_instance_queue_update(instance, true, true);
 	_instance_queue_update(instance, true, true);
+
+	if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+		_instance_update_mesh_instance(instance);
+
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+		scene_render->geometry_instance_set_skeleton(geom->geometry_instance, p_skeleton);
+	}
 }
 }
 
 
 void RendererSceneCull::instance_set_exterior(RID p_instance, bool p_enabled) {
 void RendererSceneCull::instance_set_exterior(RID p_instance, bool p_enabled) {
@@ -892,6 +945,11 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
 				}
 				}
 			}
 			}
 
 
+			if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+				InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+				scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, p_enabled);
+			}
+
 		} break;
 		} break;
 		case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: {
 		case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: {
 			if (p_enabled == instance->dynamic_gi) {
 			if (p_enabled == instance->dynamic_gi) {
@@ -907,6 +965,11 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
 			//once out of octree, can be changed
 			//once out of octree, can be changed
 			instance->dynamic_gi = p_enabled;
 			instance->dynamic_gi = p_enabled;
 
 
+			if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+				InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+				scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, p_enabled);
+			}
+
 		} break;
 		} break;
 		case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {
 		case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {
 			instance->redraw_if_visible = p_enabled;
 			instance->redraw_if_visible = p_enabled;
@@ -948,6 +1011,11 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
 		}
 		}
 	}
 	}
 
 
+	if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+		scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
+	}
+
 	_instance_queue_update(instance, false, true);
 	_instance_queue_update(instance, false, true);
 }
 }
 
 
@@ -957,6 +1025,11 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
 
 
 	instance->material_override = p_material;
 	instance->material_override = p_material;
 	_instance_queue_update(instance, false, true);
 	_instance_queue_update(instance, false, true);
+
+	if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+		scene_render->geometry_instance_set_material_override(geom->geometry_instance, p_material);
+	}
 }
 }
 
 
 void RendererSceneCull::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
 void RendererSceneCull::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
@@ -981,9 +1054,17 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
 	instance->lightmap_uv_scale = p_lightmap_uv_scale;
 	instance->lightmap_uv_scale = p_lightmap_uv_scale;
 	instance->lightmap_slice_index = p_slice_index;
 	instance->lightmap_slice_index = p_slice_index;
 
 
+	RID lightmap_instance_rid;
+
 	if (lightmap_instance) {
 	if (lightmap_instance) {
 		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data);
 		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data);
 		lightmap_data->users.insert(instance);
 		lightmap_data->users.insert(instance);
+		lightmap_instance_rid = lightmap_data->instance;
+	}
+
+	if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+		scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
 	}
 	}
 }
 }
 
 
@@ -992,16 +1073,21 @@ void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_l
 	ERR_FAIL_COND(!instance);
 	ERR_FAIL_COND(!instance);
 
 
 	instance->lod_bias = p_lod_bias;
 	instance->lod_bias = p_lod_bias;
+
+	if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+		scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, p_lod_bias);
+	}
 }
 }
 
 
 void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
 void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
 	Instance *instance = instance_owner.getornull(p_instance);
 	Instance *instance = instance_owner.getornull(p_instance);
 	ERR_FAIL_COND(!instance);
 	ERR_FAIL_COND(!instance);
 
 
-	Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
+	Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
 
 
 	if (!E) {
 	if (!E) {
-		RendererSceneRender::InstanceBase::InstanceShaderParameter isp;
+		Instance::InstanceShaderParameter isp;
 		isp.index = -1;
 		isp.index = -1;
 		isp.info = PropertyInfo();
 		isp.info = PropertyInfo();
 		isp.value = p_value;
 		isp.value = p_value;
@@ -1042,7 +1128,7 @@ void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instan
 	const_cast<RendererSceneCull *>(this)->update_dirty_instances();
 	const_cast<RendererSceneCull *>(this)->update_dirty_instances();
 
 
 	Vector<StringName> names;
 	Vector<StringName> names;
-	for (Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
+	for (Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
 		names.push_back(E->key());
 		names.push_back(E->key());
 	}
 	}
 	names.sort_custom<StringName::AlphCompare>();
 	names.sort_custom<StringName::AlphCompare>();
@@ -1079,9 +1165,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 		if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
 		if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
 			light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
 			light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
 		}
 		}
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
+	} else if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
 		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
 		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
 
 
 		scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform);
 		scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform);
@@ -1090,35 +1174,49 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 			InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
 			InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
 			idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;
 			idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;
 		}
 		}
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_DECAL) {
+	} else if (p_instance->base_type == RS::INSTANCE_DECAL) {
 		InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
 		InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
 
 
 		scene_render->decal_instance_set_transform(decal->instance, p_instance->transform);
 		scene_render->decal_instance_set_transform(decal->instance, p_instance->transform);
-	}
+	} else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
+		InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data);
 
 
-	if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
+		scene_render->lightmap_instance_set_transform(lightmap->instance, p_instance->transform);
+	} else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data);
 		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data);
 
 
 		scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform);
 		scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform);
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
+	} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
 		RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
 		RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
-	}
+	} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
+		InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(p_instance->base_data);
 
 
-	if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
 		//remove materials no longer used and un-own them
 		//remove materials no longer used and un-own them
 		if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) {
 		if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) {
 			heightfield_particle_colliders_update_list.insert(p_instance);
 			heightfield_particle_colliders_update_list.insert(p_instance);
 		}
 		}
+		RSG::storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
 	}
 	}
 
 
 	if (p_instance->aabb.has_no_surface()) {
 	if (p_instance->aabb.has_no_surface()) {
 		return;
 		return;
 	}
 	}
 
 
+	if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
+		//if this moved, update the captured objects
+		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data);
+		//erase dependencies, since no longer a lightmap
+
+		for (Set<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
+			Instance *geom = E->get();
+			_instance_queue_update(geom, true, false);
+		}
+	}
+
+	AABB new_aabb;
+	new_aabb = p_instance->transform.xform(p_instance->aabb);
+	p_instance->transformed_aabb = new_aabb;
+
 	if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
 	if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
 		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
 		//make sure lights are updated if it casts shadow
 		//make sure lights are updated if it casts shadow
@@ -1137,29 +1235,13 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 			if (!p_instance->lightmap_sh.is_empty()) {
 			if (!p_instance->lightmap_sh.is_empty()) {
 				p_instance->lightmap_sh.clear(); //don't need SH
 				p_instance->lightmap_sh.clear(); //don't need SH
 				p_instance->lightmap_target_sh.clear(); //don't need SH
 				p_instance->lightmap_target_sh.clear(); //don't need SH
+				scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, nullptr);
 			}
 			}
 		}
 		}
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
-		//if this moved, update the captured objects
-		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data);
-		//erase dependencies, since no longer a lightmap
 
 
-		for (Set<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
-			Instance *geom = E->get();
-			_instance_queue_update(geom, true, false);
-		}
+		scene_render->geometry_instance_set_transform(geom->geometry_instance, p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
 	}
 	}
 
 
-	p_instance->mirror = p_instance->transform.basis.determinant() < 0.0;
-
-	AABB new_aabb;
-
-	new_aabb = p_instance->transform.xform(p_instance->aabb);
-
-	p_instance->transformed_aabb = new_aabb;
-
 	if (p_instance->scenario == nullptr || !p_instance->visible || Math::is_zero_approx(p_instance->transform.basis.determinant())) {
 	if (p_instance->scenario == nullptr || !p_instance->visible || Math::is_zero_approx(p_instance->transform.basis.determinant())) {
 		p_instance->prev_transformed_aabb = p_instance->transformed_aabb;
 		p_instance->prev_transformed_aabb = p_instance->transformed_aabb;
 		return;
 		return;
@@ -1195,17 +1277,26 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 		idata.flags = p_instance->base_type; //changing it means de-indexing, so this never needs to be changed later
 		idata.flags = p_instance->base_type; //changing it means de-indexing, so this never needs to be changed later
 		idata.base_rid = p_instance->base;
 		idata.base_rid = p_instance->base;
 		switch (p_instance->base_type) {
 		switch (p_instance->base_type) {
+			case RS::INSTANCE_MESH:
+			case RS::INSTANCE_MULTIMESH:
+			case RS::INSTANCE_IMMEDIATE:
+			case RS::INSTANCE_PARTICLES: {
+				idata.instance_geometry = static_cast<InstanceGeometryData *>(p_instance->base_data)->geometry_instance;
+			} break;
 			case RS::INSTANCE_LIGHT: {
 			case RS::INSTANCE_LIGHT: {
-				idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance;
+				idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance.get_id();
 			} break;
 			} break;
 			case RS::INSTANCE_REFLECTION_PROBE: {
 			case RS::INSTANCE_REFLECTION_PROBE: {
-				idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance;
+				idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance.get_id();
 			} break;
 			} break;
 			case RS::INSTANCE_DECAL: {
 			case RS::INSTANCE_DECAL: {
-				idata.instance_data_rid = static_cast<InstanceDecalData *>(p_instance->base_data)->instance;
+				idata.instance_data_rid = static_cast<InstanceDecalData *>(p_instance->base_data)->instance.get_id();
+			} break;
+			case RS::INSTANCE_LIGHTMAP: {
+				idata.instance_data_rid = static_cast<InstanceLightmapData *>(p_instance->base_data)->instance.get_id();
 			} break;
 			} break;
 			case RS::INSTANCE_GI_PROBE: {
 			case RS::INSTANCE_GI_PROBE: {
-				idata.instance_data_rid = static_cast<InstanceGIProbeData *>(p_instance->base_data)->probe_instance;
+				idata.instance_data_rid = static_cast<InstanceGIProbeData *>(p_instance->base_data)->probe_instance.get_id();
 			} break;
 			} break;
 			default: {
 			default: {
 			}
 			}
@@ -1258,10 +1349,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 		pair.pair_mask |= 1 << RS::INSTANCE_GI_PROBE;
 		pair.pair_mask |= 1 << RS::INSTANCE_GI_PROBE;
 		pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP;
 		pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP;
 
 
-		if (pair_volumes_to_mesh) {
-			pair.pair_mask |= 1 << RS::INSTANCE_DECAL;
-			pair.pair_mask |= 1 << RS::INSTANCE_REFLECTION_PROBE;
-		}
+		pair.pair_mask |= geometry_instance_pair_mask;
+
 		pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
 		pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
 	} else if (p_instance->base_type == RS::INSTANCE_LIGHT) {
 	} else if (p_instance->base_type == RS::INSTANCE_LIGHT) {
 		pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK;
 		pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK;
@@ -1271,7 +1360,10 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
 			pair.pair_mask |= (1 << RS::INSTANCE_GI_PROBE);
 			pair.pair_mask |= (1 << RS::INSTANCE_GI_PROBE);
 			pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
 			pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
 		}
 		}
-	} else if (pair_volumes_to_mesh && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL)) {
+	} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) {
+		pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;
+		pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
+	} else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (p_instance->base_type == RS::INSTANCE_DECAL)) {
 		pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;
 		pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK;
 		pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
 		pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
 	} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
 	} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
@@ -1325,10 +1417,12 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
 	p_instance->array_index = -1;
 	p_instance->array_index = -1;
 	if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
 	if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
 		// Clear these now because the InstanceData containing the dirty flags is gone
 		// Clear these now because the InstanceData containing the dirty flags is gone
-		p_instance->light_instances.clear();
-		p_instance->reflection_probe_instances.clear();
-		//p_instance->decal_instances.clear(); will implement later
-		p_instance->gi_probe_instances.clear();
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+
+		scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0);
+		scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
+		scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
+		scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, nullptr, 0);
 	}
 	}
 }
 }
 
 
@@ -1486,6 +1580,8 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
 			}
 			}
 		}
 		}
 	}
 	}
+
+	scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, p_instance->lightmap_sh.ptr());
 }
 }
 
 
 void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
 void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
@@ -1849,7 +1945,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
 							}
 							}
 						}
 						}
 
 
-						geometry_instances_to_shadow_render.push_back(instance);
+						geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
 					}
 					}
 
 
 					RSG::storage->update_mesh_instances();
 					RSG::storage->update_mesh_instances();
@@ -1922,7 +2018,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
 							}
 							}
 						}
 						}
 
 
-						geometry_instances_to_shadow_render.push_back(instance);
+						geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
 					}
 					}
 
 
 					RSG::storage->update_mesh_instances();
 					RSG::storage->update_mesh_instances();
@@ -1980,7 +2076,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
 						RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
 						RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
 					}
 					}
 				}
 				}
-				geometry_instances_to_shadow_render.push_back(instance);
+				geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
 			}
 			}
 
 
 			RSG::storage->update_mesh_instances();
 			RSG::storage->update_mesh_instances();
@@ -2257,6 +2353,8 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
 		uint32_t sdfgi_last_light_index = 0xFFFFFFFF;
 		uint32_t sdfgi_last_light_index = 0xFFFFFFFF;
 		uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF;
 		uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF;
 
 
+		RID instance_pair_buffer[MAX_INSTANCE_PAIRS];
+
 		for (uint64_t i = 0; i < cull_count; i++) {
 		for (uint64_t i = 0; i < cull_count; i++) {
 			bool mesh_visible = false;
 			bool mesh_visible = false;
 
 
@@ -2268,16 +2366,16 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
 					//failure
 					//failure
 				} else if (base_type == RS::INSTANCE_LIGHT) {
 				} else if (base_type == RS::INSTANCE_LIGHT) {
 					light_cull_result.push_back(idata.instance);
 					light_cull_result.push_back(idata.instance);
-					light_instance_cull_result.push_back(idata.instance_data_rid);
+					light_instance_cull_result.push_back(RID::from_uint64(idata.instance_data_rid));
 					if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
 					if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
-						scene_render->light_instance_mark_visible(idata.instance_data_rid); //mark it visible for shadow allocation later
+						scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
 					}
 					}
 
 
 				} else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
 				} else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
 					if (render_reflection_probe != idata.instance) {
 					if (render_reflection_probe != idata.instance) {
 						//avoid entering The Matrix
 						//avoid entering The Matrix
 
 
-						if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(idata.instance_data_rid)) {
+						if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {
 							InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
 							InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
 							cull.lock.lock();
 							cull.lock.lock();
 							if (!reflection_probe->update_list.in_list()) {
 							if (!reflection_probe->update_list.in_list()) {
@@ -2289,12 +2387,12 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
 							idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
 							idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
 						}
 						}
 
 
-						if (scene_render->reflection_probe_instance_has_reflection(idata.instance_data_rid)) {
-							reflection_probe_instance_cull_result.push_back(idata.instance_data_rid);
+						if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {
+							reflection_probe_instance_cull_result.push_back(RID::from_uint64(idata.instance_data_rid));
 						}
 						}
 					}
 					}
 				} else if (base_type == RS::INSTANCE_DECAL) {
 				} else if (base_type == RS::INSTANCE_DECAL) {
-					decal_instance_cull_result.push_back(idata.instance_data_rid);
+					decal_instance_cull_result.push_back(RID::from_uint64(idata.instance_data_rid));
 
 
 				} else if (base_type == RS::INSTANCE_GI_PROBE) {
 				} else if (base_type == RS::INSTANCE_GI_PROBE) {
 					InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(idata.instance->base_data);
 					InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(idata.instance->base_data);
@@ -2303,10 +2401,10 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
 						gi_probe_update_list.add(&gi_probe->update_element);
 						gi_probe_update_list.add(&gi_probe->update_element);
 					}
 					}
 					cull.lock.unlock();
 					cull.lock.unlock();
-					gi_probe_instance_cull_result.push_back(idata.instance_data_rid);
+					gi_probe_instance_cull_result.push_back(RID::from_uint64(idata.instance_data_rid));
 
 
 				} else if (base_type == RS::INSTANCE_LIGHTMAP) {
 				} else if (base_type == RS::INSTANCE_LIGHTMAP) {
-					lightmap_cull_result.push_back(idata.instance);
+					lightmap_cull_result.push_back(RID::from_uint64(idata.instance_data_rid));
 				} else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
 				} else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
 					bool keep = true;
 					bool keep = true;
 
 
@@ -2331,68 +2429,83 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
 						}
 						}
 					}
 					}
 
 
-					if (pair_volumes_to_mesh && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
+					if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
 						InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
 						InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
-						int l = 0;
-						//only called when lights AABB enter/exit this geometry
-						idata.instance->light_instances.resize(geom->lights.size());
+						uint32_t idx = 0;
 
 
 						for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
 						for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
 							InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
 							InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
-
-							idata.instance->light_instances.write[l++] = light->instance;
+							instance_pair_buffer[idx++] = light->instance;
+							if (idx == MAX_INSTANCE_PAIRS) {
+								break;
+							}
 						}
 						}
 
 
+						scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
 						idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
 						idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
 					}
 					}
 
 
-					if (pair_volumes_to_mesh && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
+					if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
 						InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
 						InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
-						int l = 0;
-						//only called when reflection probe AABB enter/exit this geometry
-						idata.instance->reflection_probe_instances.resize(geom->reflection_probes.size());
+						uint32_t idx = 0;
 
 
 						for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
 						for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
 							InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
 							InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
 
 
-							idata.instance->reflection_probe_instances.write[l++] = reflection_probe->instance;
+							instance_pair_buffer[idx++] = reflection_probe->instance;
+							if (idx == MAX_INSTANCE_PAIRS) {
+								break;
+							}
 						}
 						}
 
 
+						scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
 						idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
 						idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
 					}
 					}
 
 
-					if (pair_volumes_to_mesh && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
+					if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
 						//InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
 						//InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
 						//todo for GLES3
 						//todo for GLES3
 						idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
 						idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
+						/*for (Set<Instance *>::Element *E = geom->dec.front(); E; E = E->next()) {
+							InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
+
+							instance_pair_buffer[idx++] = reflection_probe->instance;
+							if (idx==MAX_INSTANCE_PAIRS) {
+								break;
+							}
+						}*/
+						//scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, light_instances, idx);
 					}
 					}
 
 
 					if (idata.flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY) {
 					if (idata.flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY) {
 						InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
 						InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
-						int l = 0;
-						//only called when reflection probe AABB enter/exit this geometry
-						idata.instance->gi_probe_instances.resize(geom->gi_probes.size());
-
+						uint32_t idx = 0;
 						for (Set<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
 						for (Set<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
 							InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
 							InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
 
 
-							idata.instance->gi_probe_instances.write[l++] = gi_probe->probe_instance;
+							instance_pair_buffer[idx++] = gi_probe->probe_instance;
+							if (idx == MAX_INSTANCE_PAIRS) {
+								break;
+							}
 						}
 						}
 
 
+						scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
 						idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
 						idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
 					}
 					}
 
 
 					if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) {
 					if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) {
+						InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
 						Color *sh = idata.instance->lightmap_sh.ptrw();
 						Color *sh = idata.instance->lightmap_sh.ptrw();
 						const Color *target_sh = idata.instance->lightmap_target_sh.ptr();
 						const Color *target_sh = idata.instance->lightmap_target_sh.ptr();
 						for (uint32_t j = 0; j < 9; j++) {
 						for (uint32_t j = 0; j < 9; j++) {
 							sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
 							sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
 						}
 						}
+						scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
 						idata.instance->last_frame_pass = frame_number;
 						idata.instance->last_frame_pass = frame_number;
 					}
 					}
 
 
 					if (keep) {
 					if (keep) {
-						geometry_instances_to_render.push_back(idata.instance);
+						geometry_instances_to_render.push_back(idata.instance_geometry);
 					}
 					}
 				}
 				}
 			}
 			}
@@ -2404,7 +2517,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
 						uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
 						uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
 
 
 						if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) {
 						if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) {
-							cull.shadows[j].cascades[k].cull_result.push_back(idata.instance);
+							cull.shadows[j].cascades[k].cull_result.push_back(idata.instance_geometry);
 							mesh_visible = true;
 							mesh_visible = true;
 						}
 						}
 					}
 					}
@@ -2427,7 +2540,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
 						}
 						}
 					} else if ((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) {
 					} else if ((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) {
 						if (idata.flags & InstanceData::FLAG_USES_BAKED_LIGHT) {
 						if (idata.flags & InstanceData::FLAG_USES_BAKED_LIGHT) {
-							cull.sdfgi.region_cull_result[j].push_back(idata.instance);
+							cull.sdfgi.region_cull_result[j].push_back(idata.instance_geometry);
 							mesh_visible = true;
 							mesh_visible = true;
 						}
 						}
 					}
 					}
@@ -2654,7 +2767,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
 		environment = scenario->fallback_environment;
 		environment = scenario->fallback_environment;
 	}
 	}
 	RENDER_TIMESTAMP("Render Empty Scene ");
 	RENDER_TIMESTAMP("Render Empty Scene ");
-	scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::InstanceBase *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RendererSceneRender::InstanceBase *>(), RID(), RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
+	scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
 #endif
 #endif
 }
 }
 
 
@@ -2931,6 +3044,8 @@ void RendererSceneCull::render_probes() {
 
 
 		geometry_instances_to_render.clear();
 		geometry_instances_to_render.clear();
 
 
+		RID instance_pair_buffer[MAX_INSTANCE_PAIRS];
+
 		for (Set<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) {
 		for (Set<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) {
 			Instance *ins = E->get();
 			Instance *ins = E->get();
 			if (!ins->visible) {
 			if (!ins->visible) {
@@ -2939,21 +3054,22 @@ void RendererSceneCull::render_probes() {
 			InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;
 			InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;
 
 
 			if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY)) {
 			if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY)) {
-				//giprobes may be dirty, so update
-				int l = 0;
-				//only called when reflection probe AABB enter/exit this geometry
-				ins->gi_probe_instances.resize(geom->gi_probes.size());
-
+				uint32_t idx = 0;
 				for (Set<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
 				for (Set<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
 					InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
 					InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
 
 
-					ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance;
+					instance_pair_buffer[idx++] = gi_probe2->probe_instance;
+					if (idx == MAX_INSTANCE_PAIRS) {
+						break;
+					}
 				}
 				}
 
 
+				scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+
 				ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
 				ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
 			}
 			}
 
 
-			geometry_instances_to_render.push_back(E->get());
+			geometry_instances_to_render.push_back(geom->geometry_instance);
 		}
 		}
 
 
 		scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, geometry_instances_to_render);
 		scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, geometry_instances_to_render);
@@ -2992,7 +3108,8 @@ void RendererSceneCull::render_particle_colliders() {
 				if (!instance || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision
 				if (!instance || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision
 					continue;
 					continue;
 				}
 				}
-				geometry_instances_to_render.push_back(instance);
+				InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+				geometry_instances_to_render.push_back(geom->geometry_instance);
 			}
 			}
 
 
 			scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, geometry_instances_to_render);
 			scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, geometry_instances_to_render);
@@ -3001,7 +3118,7 @@ void RendererSceneCull::render_particle_colliders() {
 	}
 	}
 }
 }
 
 
-void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material) {
+void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
 	List<RendererStorage::InstanceShaderParam> plist;
 	List<RendererStorage::InstanceShaderParam> plist;
 	RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
 	RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
 	for (List<RendererStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) {
 	for (List<RendererStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) {
@@ -3016,7 +3133,7 @@ void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<Str
 			continue; //first one found always has priority
 			continue; //first one found always has priority
 		}
 		}
 
 
-		RendererSceneRender::InstanceBase::InstanceShaderParameter isp;
+		Instance::InstanceShaderParameter isp;
 		isp.index = E->get().index;
 		isp.index = E->get().index;
 		isp.info = E->get().info;
 		isp.info = E->get().info;
 		isp.default_value = E->get().default_value;
 		isp.default_value = E->get().default_value;
@@ -3059,7 +3176,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 
 
 			bool can_cast_shadows = true;
 			bool can_cast_shadows = true;
 			bool is_animated = false;
 			bool is_animated = false;
-			Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> isparams;
+			Map<StringName, Instance::InstanceShaderParameter> isparams;
 
 
 			if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
 			if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
 				can_cast_shadows = false;
 				can_cast_shadows = false;
@@ -3210,7 +3327,9 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 				p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
 				p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
 				if (p_instance->instance_allocated_shader_parameters) {
 				if (p_instance->instance_allocated_shader_parameters) {
 					p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
 					p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
-					for (Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
+					scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset);
+
+					for (Map<StringName, Instance::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
 						if (E->get().value.get_type() != Variant::NIL) {
 						if (E->get().value.get_type() != Variant::NIL) {
 							RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value);
 							RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value);
 						}
 						}
@@ -3218,6 +3337,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 				} else {
 				} else {
 					RSG::storage->global_variables_instance_free(p_instance->self);
 					RSG::storage->global_variables_instance_free(p_instance->self);
 					p_instance->instance_allocated_shader_parameters_offset = -1;
 					p_instance->instance_allocated_shader_parameters_offset = -1;
+					scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1);
 				}
 				}
 			}
 			}
 		}
 		}
@@ -3227,6 +3347,11 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
 		}
 		}
 
 
 		p_instance->clean_up_dependencies();
 		p_instance->clean_up_dependencies();
+
+		if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+			InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+			scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, p_instance->materials);
+		}
 	}
 	}
 
 
 	_instance_update_list.remove(&p_instance->update_item);
 	_instance_update_list.remove(&p_instance->update_item);
@@ -3322,21 +3447,24 @@ TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const Vector<RI
 
 
 RendererSceneCull *RendererSceneCull::singleton = nullptr;
 RendererSceneCull *RendererSceneCull::singleton = nullptr;
 
 
+void RendererSceneCull::set_scene_render(RendererSceneRender *p_scene_render) {
+	scene_render = p_scene_render;
+	geometry_instance_pair_mask = scene_render->geometry_instance_get_pair_mask();
+}
+
 RendererSceneCull::RendererSceneCull() {
 RendererSceneCull::RendererSceneCull() {
 	render_pass = 1;
 	render_pass = 1;
 	singleton = this;
 	singleton = this;
-	pair_volumes_to_mesh = false;
 
 
 	instance_cull_result.set_page_pool(&instance_cull_page_pool);
 	instance_cull_result.set_page_pool(&instance_cull_page_pool);
 	mesh_instance_cull_result.set_page_pool(&rid_cull_page_pool);
 	mesh_instance_cull_result.set_page_pool(&rid_cull_page_pool);
 	instance_shadow_cull_result.set_page_pool(&instance_cull_page_pool);
 	instance_shadow_cull_result.set_page_pool(&instance_cull_page_pool);
-	instance_sdfgi_cull_result.set_page_pool(&instance_cull_page_pool);
 	light_cull_result.set_page_pool(&instance_cull_page_pool);
 	light_cull_result.set_page_pool(&instance_cull_page_pool);
 
 
-	geometry_instances_to_render.set_page_pool(&base_instance_cull_page_pool);
-	geometry_instances_to_shadow_render.set_page_pool(&base_instance_cull_page_pool);
-	lightmap_cull_result.set_page_pool(&base_instance_cull_page_pool);
+	geometry_instances_to_render.set_page_pool(&geometry_instance_cull_page_pool);
+	geometry_instances_to_shadow_render.set_page_pool(&geometry_instance_cull_page_pool);
 
 
+	lightmap_cull_result.set_page_pool(&rid_cull_page_pool);
 	reflection_probe_instance_cull_result.set_page_pool(&rid_cull_page_pool);
 	reflection_probe_instance_cull_result.set_page_pool(&rid_cull_page_pool);
 	light_instance_cull_result.set_page_pool(&rid_cull_page_pool);
 	light_instance_cull_result.set_page_pool(&rid_cull_page_pool);
 	gi_probe_instance_cull_result.set_page_pool(&rid_cull_page_pool);
 	gi_probe_instance_cull_result.set_page_pool(&rid_cull_page_pool);
@@ -3344,12 +3472,12 @@ RendererSceneCull::RendererSceneCull() {
 
 
 	for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
 	for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
 		for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
 		for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
-			cull.shadows[i].cascades[j].cull_result.set_page_pool(&base_instance_cull_page_pool);
+			cull.shadows[i].cascades[j].cull_result.set_page_pool(&geometry_instance_cull_page_pool);
 		}
 		}
 	}
 	}
 
 
 	for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
 	for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
-		cull.sdfgi.region_cull_result[i].set_page_pool(&base_instance_cull_page_pool);
+		cull.sdfgi.region_cull_result[i].set_page_pool(&geometry_instance_cull_page_pool);
 	}
 	}
 
 
 	for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
 	for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
@@ -3363,7 +3491,6 @@ RendererSceneCull::~RendererSceneCull() {
 	instance_cull_result.reset();
 	instance_cull_result.reset();
 	mesh_instance_cull_result.reset();
 	mesh_instance_cull_result.reset();
 	instance_shadow_cull_result.reset();
 	instance_shadow_cull_result.reset();
-	instance_sdfgi_cull_result.reset();
 	light_cull_result.reset();
 	light_cull_result.reset();
 
 
 	geometry_instances_to_render.reset();
 	geometry_instances_to_render.reset();

+ 86 - 13
servers/rendering/renderer_scene_cull.h

@@ -53,7 +53,8 @@ public:
 
 
 	enum {
 	enum {
 		SDFGI_MAX_CASCADES = 8,
 		SDFGI_MAX_CASCADES = 8,
-		SDFGI_MAX_REGIONS_PER_CASCADE = 3
+		SDFGI_MAX_REGIONS_PER_CASCADE = 3,
+		MAX_INSTANCE_PAIRS = 32
 	};
 	};
 
 
 	uint64_t render_pass;
 	uint64_t render_pass;
@@ -249,7 +250,10 @@ public:
 		uint32_t flags = 0;
 		uint32_t flags = 0;
 		uint32_t layer_mask = 0; //for fast layer-mask discard
 		uint32_t layer_mask = 0; //for fast layer-mask discard
 		RID base_rid;
 		RID base_rid;
-		RID instance_data_rid;
+		union {
+			uint64_t instance_data_rid;
+			RendererSceneRender::GeometryInstance *instance_geometry;
+		};
 		Instance *instance = nullptr;
 		Instance *instance = nullptr;
 	};
 	};
 
 
@@ -296,7 +300,7 @@ public:
 	static void _instance_pair(Instance *p_A, Instance *p_B);
 	static void _instance_pair(Instance *p_A, Instance *p_B);
 	static void _instance_unpair(Instance *p_A, Instance *p_B);
 	static void _instance_unpair(Instance *p_A, Instance *p_B);
 
 
-	static void _instance_update_mesh_instance(Instance *p_instance);
+	void _instance_update_mesh_instance(Instance *p_instance);
 
 
 	virtual RID scenario_create();
 	virtual RID scenario_create();
 
 
@@ -325,7 +329,55 @@ public:
 		virtual ~InstanceBaseData() {}
 		virtual ~InstanceBaseData() {}
 	};
 	};
 
 
-	struct Instance : RendererSceneRender::InstanceBase {
+	struct Instance : public RendererStorage::InstanceBaseDependency {
+		RS::InstanceType base_type;
+		RID base;
+
+		RID skeleton;
+		RID material_override;
+
+		RID mesh_instance; //only used for meshes and when skeleton/blendshapes exist
+
+		Transform transform;
+
+		float lod_bias;
+
+		Vector<RID> materials;
+
+		RS::ShadowCastingSetting cast_shadows;
+
+		uint32_t layer_mask;
+		//fit in 32 bits
+		bool mirror : 8;
+		bool receive_shadows : 8;
+		bool visible : 8;
+		bool baked_light : 2; //this flag is only to know if it actually did use baked light
+		bool dynamic_gi : 2; //this flag is only to know if it actually did use baked light
+		bool redraw_if_visible : 4;
+
+		Instance *lightmap;
+		Rect2 lightmap_uv_scale;
+		int lightmap_slice_index;
+		uint32_t lightmap_cull_index;
+		Vector<Color> lightmap_sh; //spherical harmonic
+
+		AABB aabb;
+		AABB transformed_aabb;
+		AABB prev_transformed_aabb;
+
+		struct InstanceShaderParameter {
+			int32_t index = -1;
+			Variant value;
+			Variant default_value;
+			PropertyInfo info;
+		};
+
+		Map<StringName, InstanceShaderParameter> instance_shader_parameters;
+		bool instance_allocated_shader_parameters = false;
+		int32_t instance_allocated_shader_parameters_offset = -1;
+
+		//
+
 		RID self;
 		RID self;
 		//scenario stuff
 		//scenario stuff
 		DynamicBVH::ID indexer_id;
 		DynamicBVH::ID indexer_id;
@@ -377,6 +429,20 @@ public:
 		Instance() :
 		Instance() :
 				scenario_item(this),
 				scenario_item(this),
 				update_item(this) {
 				update_item(this) {
+			base_type = RS::INSTANCE_NONE;
+			cast_shadows = RS::SHADOW_CASTING_SETTING_ON;
+			receive_shadows = true;
+			visible = true;
+			layer_mask = 1;
+			instance_version = 0;
+			baked_light = false;
+			dynamic_gi = false;
+			redraw_if_visible = false;
+			lightmap_slice_index = 0;
+			lightmap = nullptr;
+			lightmap_cull_index = 0;
+			lod_bias = 1.0;
+
 			scenario = nullptr;
 			scenario = nullptr;
 
 
 			update_aabb = false;
 			update_aabb = false;
@@ -415,6 +481,7 @@ public:
 	void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
 	void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
 
 
 	struct InstanceGeometryData : public InstanceBaseData {
 	struct InstanceGeometryData : public InstanceBaseData {
+		RendererSceneRender::GeometryInstance *geometry_instance = nullptr;
 		Set<Instance *> lights;
 		Set<Instance *> lights;
 		bool can_cast_shadows;
 		bool can_cast_shadows;
 		bool material_is_animated;
 		bool material_is_animated;
@@ -458,6 +525,10 @@ public:
 
 
 	SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
 	SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
 
 
+	struct InstanceParticlesCollisionData : public InstanceBaseData {
+		RID instance;
+	};
+
 	struct InstanceLightData : public InstanceBaseData {
 	struct InstanceLightData : public InstanceBaseData {
 		RID instance;
 		RID instance;
 		uint64_t last_version;
 		uint64_t last_version;
@@ -523,6 +594,7 @@ public:
 	SelfList<InstanceGIProbeData>::List gi_probe_update_list;
 	SelfList<InstanceGIProbeData>::List gi_probe_update_list;
 
 
 	struct InstanceLightmapData : public InstanceBaseData {
 	struct InstanceLightmapData : public InstanceBaseData {
+		RID instance;
 		Set<Instance *> geometries;
 		Set<Instance *> geometries;
 		Set<Instance *> users;
 		Set<Instance *> users;
 
 
@@ -600,17 +672,16 @@ public:
 	Set<Instance *> heightfield_particle_colliders_update_list;
 	Set<Instance *> heightfield_particle_colliders_update_list;
 
 
 	PagedArrayPool<Instance *> instance_cull_page_pool;
 	PagedArrayPool<Instance *> instance_cull_page_pool;
-	PagedArrayPool<RendererSceneRender::InstanceBase *> base_instance_cull_page_pool;
+	PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool;
 	PagedArrayPool<RID> rid_cull_page_pool;
 	PagedArrayPool<RID> rid_cull_page_pool;
 
 
 	PagedArray<Instance *> instance_cull_result;
 	PagedArray<Instance *> instance_cull_result;
 	PagedArray<RID> mesh_instance_cull_result;
 	PagedArray<RID> mesh_instance_cull_result;
-	PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_render;
+	PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances_to_render;
 	PagedArray<Instance *> instance_shadow_cull_result;
 	PagedArray<Instance *> instance_shadow_cull_result;
-	PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_shadow_render;
-	PagedArray<Instance *> instance_sdfgi_cull_result;
+	PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances_to_shadow_render;
 	PagedArray<Instance *> light_cull_result;
 	PagedArray<Instance *> light_cull_result;
-	PagedArray<RendererSceneRender::InstanceBase *> lightmap_cull_result;
+	PagedArray<RID> lightmap_cull_result;
 	PagedArray<RID> reflection_probe_instance_cull_result;
 	PagedArray<RID> reflection_probe_instance_cull_result;
 	PagedArray<RID> light_instance_cull_result;
 	PagedArray<RID> light_instance_cull_result;
 
 
@@ -619,7 +690,7 @@ public:
 
 
 	RID_PtrOwner<Instance> instance_owner;
 	RID_PtrOwner<Instance> instance_owner;
 
 
-	bool pair_volumes_to_mesh; // used in traditional forward, unnecesary on clustered
+	uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecesary on clustered
 
 
 	virtual RID instance_create();
 	virtual RID instance_create();
 
 
@@ -653,7 +724,7 @@ public:
 	virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
 	virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
 	virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
 	virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
 
 
-	void _update_instance_shader_parameters_from_material(Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material);
+	void _update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material);
 
 
 	virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value);
 	virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value);
 	virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
 	virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
@@ -687,7 +758,7 @@ public:
 				real_t range_begin;
 				real_t range_begin;
 				Vector2 uv_scale;
 				Vector2 uv_scale;
 
 
-				PagedArray<RendererSceneRender::InstanceBase *> cull_result;
+				PagedArray<RendererSceneRender::GeometryInstance *> cull_result;
 
 
 			} cascades[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES]; //max 4 cascades
 			} cascades[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES]; //max 4 cascades
 			uint32_t cascade_count;
 			uint32_t cascade_count;
@@ -698,7 +769,7 @@ public:
 
 
 		struct SDFGI {
 		struct SDFGI {
 			//have arrays here because SDFGI functions expects this, plus regions can have areas
 			//have arrays here because SDFGI functions expects this, plus regions can have areas
-			PagedArray<RendererSceneRender::InstanceBase *> region_cull_result[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
+			PagedArray<RendererSceneRender::GeometryInstance *> region_cull_result[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
 			AABB region_aabb[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade
 			AABB region_aabb[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade
 			uint32_t region_cascade[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade
 			uint32_t region_cascade[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade
 			uint32_t region_count = 0;
 			uint32_t region_count = 0;
@@ -828,6 +899,8 @@ public:
 
 
 	bool free(RID p_rid);
 	bool free(RID p_rid);
 
 
+	void set_scene_render(RendererSceneRender *p_scene_render);
+
 	RendererSceneCull();
 	RendererSceneCull();
 	virtual ~RendererSceneCull();
 	virtual ~RendererSceneCull();
 };
 };

+ 37 - 85
servers/rendering/renderer_scene_render.h

@@ -41,6 +41,34 @@ public:
 		MAX_DIRECTIONAL_LIGHTS = 8,
 		MAX_DIRECTIONAL_LIGHTS = 8,
 		MAX_DIRECTIONAL_LIGHT_CASCADES = 4
 		MAX_DIRECTIONAL_LIGHT_CASCADES = 4
 	};
 	};
+
+	struct GeometryInstance {
+		virtual ~GeometryInstance() {}
+	};
+
+	virtual GeometryInstance *geometry_instance_create(RID p_base) = 0;
+	virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0;
+	virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0;
+	virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0;
+	virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0;
+	virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
+	virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0;
+	virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0;
+	virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+	virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+	virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
+	virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) = 0;
+	virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) = 0;
+	virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+
+	virtual uint32_t geometry_instance_get_pair_mask() = 0;
+	virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
+	virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
+	virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
+	virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) = 0;
+
+	virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0;
+
 	/* SHADOW ATLAS API */
 	/* SHADOW ATLAS API */
 
 
 	virtual RID
 	virtual RID
@@ -55,8 +83,6 @@ public:
 
 
 	/* SDFGI UPDATE */
 	/* SDFGI UPDATE */
 
 
-	struct InstanceBase;
-
 	virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
 	virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
 	virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
 	virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
 	virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
 	virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
@@ -134,83 +160,6 @@ public:
 	virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
 	virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
 	virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
 	virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
 
 
-	struct InstanceBase : public RendererStorage::InstanceBaseDependency {
-		RS::InstanceType base_type;
-		RID base;
-
-		RID skeleton;
-		RID material_override;
-
-		RID mesh_instance; //only used for meshes and when skeleton/blendshapes exist
-
-		Transform transform;
-
-		float lod_bias;
-
-		int depth_layer;
-		uint32_t layer_mask;
-
-		//RID sampled_light;
-
-		Vector<RID> materials;
-		Vector<RID> light_instances;
-		Vector<RID> reflection_probe_instances;
-		Vector<RID> gi_probe_instances;
-
-		RS::ShadowCastingSetting cast_shadows;
-
-		//fit in 32 bits
-		bool mirror : 8;
-		bool receive_shadows : 8;
-		bool visible : 8;
-		bool baked_light : 2; //this flag is only to know if it actually did use baked light
-		bool dynamic_gi : 2; //this flag is only to know if it actually did use baked light
-		bool redraw_if_visible : 4;
-
-		float depth; //used for sorting
-
-		InstanceBase *lightmap;
-		Rect2 lightmap_uv_scale;
-		int lightmap_slice_index;
-		uint32_t lightmap_cull_index;
-		Vector<Color> lightmap_sh; //spherical harmonic
-
-		AABB aabb;
-		AABB transformed_aabb;
-		AABB prev_transformed_aabb;
-
-		struct InstanceShaderParameter {
-			int32_t index = -1;
-			Variant value;
-			Variant default_value;
-			PropertyInfo info;
-		};
-
-		Map<StringName, InstanceShaderParameter> instance_shader_parameters;
-		bool instance_allocated_shader_parameters = false;
-		int32_t instance_allocated_shader_parameters_offset = -1;
-
-		InstanceBase() {
-			base_type = RS::INSTANCE_NONE;
-			cast_shadows = RS::SHADOW_CASTING_SETTING_ON;
-			receive_shadows = true;
-			visible = true;
-			depth_layer = 0;
-			layer_mask = 1;
-			instance_version = 0;
-			baked_light = false;
-			dynamic_gi = false;
-			redraw_if_visible = false;
-			lightmap_slice_index = 0;
-			lightmap = nullptr;
-			lightmap_cull_index = 0;
-			lod_bias = 1.0;
-		}
-
-		virtual ~InstanceBase() {
-		}
-	};
-
 	virtual RID light_instance_create(RID p_light) = 0;
 	virtual RID light_instance_create(RID p_light) = 0;
 	virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
 	virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
 	virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
 	virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
@@ -235,20 +184,23 @@ public:
 	virtual RID decal_instance_create(RID p_decal) = 0;
 	virtual RID decal_instance_create(RID p_decal) = 0;
 	virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform) = 0;
 	virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform) = 0;
 
 
+	virtual RID lightmap_instance_create(RID p_lightmap) = 0;
+	virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) = 0;
+
 	virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
 	virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
 	virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
 	virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
 	virtual bool gi_probe_needs_update(RID p_probe) const = 0;
 	virtual bool gi_probe_needs_update(RID p_probe) const = 0;
-	virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects) = 0;
+	virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0;
 
 
 	virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
 	virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
 
 
-	virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
+	virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
 
 
-	virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
-	virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
-	virtual void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) = 0;
+	virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
+	virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+	virtual void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) = 0;
 	virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_lights) = 0;
 	virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_lights) = 0;
-	virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) = 0;
+	virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
 
 
 	virtual void set_scene_pass(uint64_t p_pass) = 0;
 	virtual void set_scene_pass(uint64_t p_pass) = 0;
 	virtual void set_time(double p_time, double p_step) = 0;
 	virtual void set_time(double p_time, double p_step) = 0;

+ 7 - 2
servers/rendering/renderer_storage.h

@@ -474,8 +474,8 @@ public:
 
 
 	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis) = 0;
 	virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis) = 0;
 
 
-	virtual void particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance) = 0;
-	virtual void particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance) = 0;
+	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
+	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
 
 
 	virtual void update_particles() = 0;
 	virtual void update_particles() = 0;
 
 
@@ -496,6 +496,11 @@ public:
 	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
 	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
 	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
 	virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
 
 
+	//used from 2D and 3D
+	virtual RID particles_collision_instance_create(RID p_collision) = 0;
+	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) = 0;
+	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
+
 	/* GLOBAL VARIABLES */
 	/* GLOBAL VARIABLES */
 
 
 	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
 	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;

+ 1 - 1
servers/rendering/rendering_server_default.cpp

@@ -267,7 +267,7 @@ RenderingServerDefault::RenderingServerDefault() {
 	RSG::rasterizer = RendererCompositor::create();
 	RSG::rasterizer = RendererCompositor::create();
 	RSG::storage = RSG::rasterizer->get_storage();
 	RSG::storage = RSG::rasterizer->get_storage();
 	RSG::canvas_render = RSG::rasterizer->get_canvas();
 	RSG::canvas_render = RSG::rasterizer->get_canvas();
-	sr->scene_render = RSG::rasterizer->get_scene();
+	sr->set_scene_render(RSG::rasterizer->get_scene());
 
 
 	frame_profile_frame = 0;
 	frame_profile_frame = 0;