Prechádzať zdrojové kódy

Reorganize rendering server.

-Made RenderingServerScene abstract, allowing reimplementation
-RenderingServerRaster -> RenderingServerDefault, but this class is going away soon.
reduz 4 rokov pred
rodič
commit
e93b2242c2

+ 100 - 0
core/templates/pass_func.h

@@ -0,0 +1,100 @@
+/*************************************************************************/
+/*  pass_func.h                                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef PASS_FUNC_H
+#define PASS_FUNC_H
+
+#define PASS0R(m_r, m_name) \
+	m_r m_name() { return PASSBASE->m_name(); }
+#define PASS0RC(m_r, m_name) \
+	m_r m_name() const { return PASSBASE->m_name(); }
+#define PASS1R(m_r, m_name, m_type1) \
+	m_r m_name(m_type1 arg1) { return PASSBASE->m_name(arg1); }
+#define PASS1RC(m_r, m_name, m_type1) \
+	m_r m_name(m_type1 arg1) const { return PASSBASE->m_name(arg1); }
+#define PASS2R(m_r, m_name, m_type1, m_type2) \
+	m_r m_name(m_type1 arg1, m_type2 arg2) { return PASSBASE->m_name(arg1, arg2); }
+#define PASS2RC(m_r, m_name, m_type1, m_type2) \
+	m_r m_name(m_type1 arg1, m_type2 arg2) const { return PASSBASE->m_name(arg1, arg2); }
+#define PASS3R(m_r, m_name, m_type1, m_type2, m_type3) \
+	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { return PASSBASE->m_name(arg1, arg2, arg3); }
+#define PASS3RC(m_r, m_name, m_type1, m_type2, m_type3) \
+	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return PASSBASE->m_name(arg1, arg2, arg3); }
+#define PASS4R(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
+	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { return PASSBASE->m_name(arg1, arg2, arg3, arg4); }
+#define PASS4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
+	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return PASSBASE->m_name(arg1, arg2, arg3, arg4); }
+#define PASS5R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
+	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { return PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
+#define PASS5RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
+	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) const { return PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
+#define PASS6R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
+	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { return PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
+#define PASS6RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
+	m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) const { return PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
+
+#define PASS0(m_name) \
+	void m_name() { PASSBASE->m_name(); }
+#define PASS1(m_name, m_type1) \
+	void m_name(m_type1 arg1) { PASSBASE->m_name(arg1); }
+#define PASS1C(m_name, m_type1) \
+	void m_name(m_type1 arg1) const { PASSBASE->m_name(arg1); }
+#define PASS2(m_name, m_type1, m_type2) \
+	void m_name(m_type1 arg1, m_type2 arg2) { PASSBASE->m_name(arg1, arg2); }
+#define PASS2C(m_name, m_type1, m_type2) \
+	void m_name(m_type1 arg1, m_type2 arg2) const { PASSBASE->m_name(arg1, arg2); }
+#define PASS3(m_name, m_type1, m_type2, m_type3) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { PASSBASE->m_name(arg1, arg2, arg3); }
+#define PASS4(m_name, m_type1, m_type2, m_type3, m_type4) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { PASSBASE->m_name(arg1, arg2, arg3, arg4); }
+#define PASS5(m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
+#define PASS6(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
+#define PASS7(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
+#define PASS8(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
+#define PASS9(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); }
+#define PASS10(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); }
+#define PASS11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); }
+#define PASS12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); }
+#define PASS13(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); }
+#define PASS14(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); }
+#define PASS15(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14, m_type15) \
+	void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14, m_type15 arg15) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); }
+
+#endif // PASS_FUNC_H

+ 2 - 2
main/main.cpp

@@ -70,7 +70,7 @@
 #include "servers/physics_server_2d.h"
 #include "servers/physics_server_3d.h"
 #include "servers/register_server_types.h"
-#include "servers/rendering/rendering_server_raster.h"
+#include "servers/rendering/rendering_server_default.h"
 #include "servers/rendering/rendering_server_wrap_mt.h"
 #include "servers/text_server.h"
 #include "servers/xr_server.h"
@@ -1563,7 +1563,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
 
 	/* Initialize Visual Server */
 
-	rendering_server = memnew(RenderingServerRaster);
+	rendering_server = memnew(RenderingServerDefault);
 	if (OS::get_singleton()->get_render_thread_mode() != OS::RENDER_THREAD_UNSAFE) {
 		rendering_server = memnew(RenderingServerWrapMT(rendering_server,
 				OS::get_singleton()->get_render_thread_mode() ==

+ 1 - 1
platform/iphone/display_server_iphone.mm

@@ -73,7 +73,7 @@ DisplayServerIPhone::DisplayServerIPhone(const String &p_rendering_driver, Displ
 			//        return ERR_UNAVAILABLE;
 		}
 
-		//    rendering_server = memnew(RenderingServerRaster);
+		//    rendering_server = memnew(RenderingServerDefault);
 		//    // FIXME: Reimplement threaded rendering
 		//    if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
 		//        rendering_server = memnew(RenderingServerWrapMT(rendering_server,

+ 1 - 1
platform/linuxbsd/display_server_x11.cpp

@@ -4093,7 +4093,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
 #endif
 
 	/*
-	rendering_server = memnew(RenderingServerRaster);
+	rendering_server = memnew(RenderingServerDefault);
 	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
 		rendering_server = memnew(RenderingServerWrapMT(rendering_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
 	}

+ 2 - 2
platform/server/os_server.cpp

@@ -33,7 +33,7 @@
 #include "core/string/print_string.h"
 #include "drivers/dummy/rasterizer_dummy.h"
 #include "drivers/dummy/texture_loader_dummy.h"
-#include "servers/rendering/rendering_server_raster.h"
+#include "servers/rendering/rendering_server_default.h"
 
 #include "main/main.h"
 
@@ -76,7 +76,7 @@ Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int
 
 	video_driver_index = p_video_driver; // unused in server platform, but should still be initialized
 
-	rendering_server = memnew(RenderingServerRaster);
+	rendering_server = memnew(RenderingServerDefault);
 	rendering_server->init();
 
 	AudioDriverManager::initialize(p_audio_driver);

+ 2 - 2
platform/uwp/os_uwp.cpp

@@ -44,7 +44,7 @@
 #include "main/main.h"
 #include "platform/windows/windows_terminal_logger.h"
 #include "servers/audio_server.h"
-#include "servers/rendering/rendering_server_raster.h"
+#include "servers/rendering/rendering_server_default.h"
 #include "servers/rendering/rendering_server_wrap_mt.h"
 #include "thread_uwp.h"
 
@@ -240,7 +240,7 @@ Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
 
 	set_video_mode(vm);
 
-	rendering_server = memnew(RenderingServerRaster);
+	rendering_server = memnew(RenderingServerDefault);
 	// FIXME: Reimplement threaded rendering
 	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
 		rendering_server = memnew(RenderingServerWrapMT(rendering_server, false));

+ 1 - 1
platform/windows/os_windows.cpp

@@ -46,7 +46,7 @@
 #include "main/main.h"
 #include "platform/windows/display_server_windows.h"
 #include "servers/audio_server.h"
-#include "servers/rendering/rendering_server_raster.h"
+#include "servers/rendering/rendering_server_default.h"
 #include "servers/rendering/rendering_server_wrap_mt.h"
 #include "windows_terminal_logger.h"
 

+ 1 - 1
servers/display_server.h

@@ -83,7 +83,7 @@ protected:
 	static DisplayServerCreate server_create_functions[MAX_SERVERS];
 	static int server_create_count;
 
-	friend class RenderingServerRaster;
+	friend class RenderingServerDefault;
 	virtual void _set_use_vsync(bool p_enable);
 
 public:

+ 1 - 1
servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp

@@ -874,7 +874,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
 
 				glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white
 
-				RenderingServerRaster::redraw_request();
+				RenderingServerDefault::redraw_request();
 
 				storage->particles_request_process(particles_cmd->particles);
 				//enable instancing

+ 2 - 2
servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp

@@ -31,7 +31,7 @@
 #include "rasterizer_scene_high_end_rd.h"
 #include "core/config/project_settings.h"
 #include "servers/rendering/rendering_device.h"
-#include "servers/rendering/rendering_server_raster.h"
+#include "servers/rendering/rendering_server_default.h"
 
 /* SCENE SHADER */
 void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
@@ -1512,7 +1512,7 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta
 	e->priority = p_material->priority;
 
 	if (p_material->shader_data->uses_time) {
-		RenderingServerRaster::redraw_request();
+		RenderingServerDefault::redraw_request();
 	}
 }
 

+ 3 - 3
servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp

@@ -33,7 +33,7 @@
 #include "core/config/project_settings.h"
 #include "core/os/os.h"
 #include "rasterizer_rd.h"
-#include "servers/rendering/rendering_server_raster.h"
+#include "servers/rendering/rendering_server_default.h"
 
 uint64_t RasterizerSceneRD::auto_exposure_counter = 2;
 
@@ -2242,7 +2242,7 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, RID p_render_buffers, cons
 		if (shader_data->uses_time && time - sky->prev_time > 0.00001) {
 			sky->prev_time = time;
 			sky->reflection.dirty = true;
-			RenderingServerRaster::redraw_request();
+			RenderingServerDefault::redraw_request();
 		}
 
 		if (material != sky->prev_material) {
@@ -5257,7 +5257,7 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu
 
 		//swap final reduce with prev luminance
 		SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
-		RenderingServerRaster::redraw_request(); //redraw all the time if auto exposure rendering is on
+		RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on
 	}
 
 	int max_glow_level = -1;

+ 2 - 2
servers/rendering/rendering_server_canvas.cpp

@@ -31,8 +31,8 @@
 #include "rendering_server_canvas.h"
 
 #include "core/math/geometry_2d.h"
+#include "rendering_server_default.h"
 #include "rendering_server_globals.h"
-#include "rendering_server_raster.h"
 #include "rendering_server_viewport.h"
 
 static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
@@ -263,7 +263,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo
 	}
 
 	if (ci->update_when_visible) {
-		RenderingServerRaster::redraw_request();
+		RenderingServerDefault::redraw_request();
 	}
 
 	if ((ci->commands != nullptr && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {

+ 36 - 41
servers/rendering/rendering_server_raster.cpp → servers/rendering/rendering_server_default.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  rendering_server_raster.cpp                                          */
+/*  rendering_server_default.cpp                                         */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,7 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "rendering_server_raster.h"
+#include "rendering_server_default.h"
 
 #include "core/config/project_settings.h"
 #include "core/io/marshalls.h"
@@ -36,35 +36,35 @@
 #include "core/templates/sort_array.h"
 #include "rendering_server_canvas.h"
 #include "rendering_server_globals.h"
-#include "rendering_server_scene.h"
+#include "rendering_server_scene_raster.h"
 
 // careful, these may run in different threads than the visual server
 
-int RenderingServerRaster::changes = 0;
+int RenderingServerDefault::changes = 0;
 
 /* BLACK BARS */
 
-void RenderingServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) {
+void RenderingServerDefault::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) {
 	black_margin[MARGIN_LEFT] = p_left;
 	black_margin[MARGIN_TOP] = p_top;
 	black_margin[MARGIN_RIGHT] = p_right;
 	black_margin[MARGIN_BOTTOM] = p_bottom;
 }
 
-void RenderingServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) {
+void RenderingServerDefault::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) {
 	black_image[MARGIN_LEFT] = p_left;
 	black_image[MARGIN_TOP] = p_top;
 	black_image[MARGIN_RIGHT] = p_right;
 	black_image[MARGIN_BOTTOM] = p_bottom;
 }
 
-void RenderingServerRaster::_draw_margins() {
+void RenderingServerDefault::_draw_margins() {
 	RSG::canvas_render->draw_window_margins(black_margin, black_image);
 };
 
 /* FREE */
 
-void RenderingServerRaster::free(RID p_rid) {
+void RenderingServerDefault::free(RID p_rid) {
 	if (RSG::storage->free(p_rid)) {
 		return;
 	}
@@ -77,14 +77,11 @@ void RenderingServerRaster::free(RID p_rid) {
 	if (RSG::scene->free(p_rid)) {
 		return;
 	}
-	if (RSG::scene_render->free(p_rid)) {
-		return;
-	}
 }
 
 /* EVENT QUEUING */
 
-void RenderingServerRaster::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) {
+void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) {
 	ERR_FAIL_NULL(p_where);
 	FrameDrawnCallbacks fdc;
 	fdc.object = p_where->get_instance_id();
@@ -94,7 +91,7 @@ void RenderingServerRaster::request_frame_drawn_callback(Object *p_where, const
 	frame_drawn_callbacks.push_back(fdc);
 }
 
-void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
+void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
 	//needs to be done before changes is reset to 0, to not force the editor to redraw
 	RS::get_singleton()->emit_signal("frame_pre_draw");
 
@@ -104,11 +101,8 @@ void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
 
 	TIMESTAMP_BEGIN()
 
-	RSG::scene_render->update(); //update scenes stuff before updating instances
-
-	RSG::scene->update_dirty_instances(); //update scene stuff
+	RSG::scene->update(); //update scenes stuff before updating instances
 
-	RSG::scene->render_particle_colliders();
 	RSG::storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered
 
 	RSG::scene->render_probes();
@@ -165,18 +159,18 @@ void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
 	frame_profile_frame = RSG::storage->get_captured_timestamps_frame();
 }
 
-void RenderingServerRaster::sync() {
+void RenderingServerDefault::sync() {
 }
 
-bool RenderingServerRaster::has_changed() const {
+bool RenderingServerDefault::has_changed() const {
 	return changes > 0;
 }
 
-void RenderingServerRaster::init() {
+void RenderingServerDefault::init() {
 	RSG::rasterizer->initialize();
 }
 
-void RenderingServerRaster::finish() {
+void RenderingServerDefault::finish() {
 	if (test_cube.is_valid()) {
 		free(test_cube);
 	}
@@ -186,69 +180,69 @@ void RenderingServerRaster::finish() {
 
 /* STATUS INFORMATION */
 
-int RenderingServerRaster::get_render_info(RenderInfo p_info) {
+int RenderingServerDefault::get_render_info(RenderInfo p_info) {
 	return RSG::storage->get_render_info(p_info);
 }
 
-String RenderingServerRaster::get_video_adapter_name() const {
+String RenderingServerDefault::get_video_adapter_name() const {
 	return RSG::storage->get_video_adapter_name();
 }
 
-String RenderingServerRaster::get_video_adapter_vendor() const {
+String RenderingServerDefault::get_video_adapter_vendor() const {
 	return RSG::storage->get_video_adapter_vendor();
 }
 
-void RenderingServerRaster::set_frame_profiling_enabled(bool p_enable) {
+void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
 	RSG::storage->capturing_timestamps = p_enable;
 }
 
-uint64_t RenderingServerRaster::get_frame_profile_frame() {
+uint64_t RenderingServerDefault::get_frame_profile_frame() {
 	return frame_profile_frame;
 }
 
-Vector<RenderingServer::FrameProfileArea> RenderingServerRaster::get_frame_profile() {
+Vector<RenderingServer::FrameProfileArea> RenderingServerDefault::get_frame_profile() {
 	return frame_profile;
 }
 
 /* TESTING */
 
-void RenderingServerRaster::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
+void RenderingServerDefault::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
 	redraw_request();
 	RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter);
 }
 
-void RenderingServerRaster::set_default_clear_color(const Color &p_color) {
+void RenderingServerDefault::set_default_clear_color(const Color &p_color) {
 	RSG::viewport->set_default_clear_color(p_color);
 }
 
-bool RenderingServerRaster::has_feature(Features p_feature) const {
+bool RenderingServerDefault::has_feature(Features p_feature) const {
 	return false;
 }
 
-void RenderingServerRaster::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {
-	RSG::scene_render->sdfgi_set_debug_probe_select(p_position, p_dir);
+void RenderingServerDefault::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {
+	RSG::scene->sdfgi_set_debug_probe_select(p_position, p_dir);
 }
 
-RID RenderingServerRaster::get_test_cube() {
+RID RenderingServerDefault::get_test_cube() {
 	if (!test_cube.is_valid()) {
 		test_cube = _make_test_cube();
 	}
 	return test_cube;
 }
 
-bool RenderingServerRaster::has_os_feature(const String &p_feature) const {
+bool RenderingServerDefault::has_os_feature(const String &p_feature) const {
 	return RSG::storage->has_os_feature(p_feature);
 }
 
-void RenderingServerRaster::set_debug_generate_wireframes(bool p_generate) {
+void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
 	RSG::storage->set_debug_generate_wireframes(p_generate);
 }
 
-void RenderingServerRaster::call_set_use_vsync(bool p_enable) {
+void RenderingServerDefault::call_set_use_vsync(bool p_enable) {
 	DisplayServer::get_singleton()->_set_use_vsync(p_enable);
 }
 
-bool RenderingServerRaster::is_low_end() const {
+bool RenderingServerDefault::is_low_end() const {
 	// FIXME: Commented out when rebasing vulkan branch on master,
 	// causes a crash, it seems rasterizer is not initialized yet the
 	// first time it's called.
@@ -256,14 +250,15 @@ bool RenderingServerRaster::is_low_end() const {
 	return false;
 }
 
-RenderingServerRaster::RenderingServerRaster() {
+RenderingServerDefault::RenderingServerDefault() {
 	RSG::canvas = memnew(RenderingServerCanvas);
 	RSG::viewport = memnew(RenderingServerViewport);
-	RSG::scene = memnew(RenderingServerScene);
+	RenderingServerSceneRaster *sr = memnew(RenderingServerSceneRaster);
+	RSG::scene = sr;
 	RSG::rasterizer = Rasterizer::create();
 	RSG::storage = RSG::rasterizer->get_storage();
 	RSG::canvas_render = RSG::rasterizer->get_canvas();
-	RSG::scene_render = RSG::rasterizer->get_scene();
+	sr->scene_render = RSG::rasterizer->get_scene();
 
 	frame_profile_frame = 0;
 
@@ -273,7 +268,7 @@ RenderingServerRaster::RenderingServerRaster() {
 	}
 }
 
-RenderingServerRaster::~RenderingServerRaster() {
+RenderingServerDefault::~RenderingServerDefault() {
 	memdelete(RSG::canvas);
 	memdelete(RSG::viewport);
 	memdelete(RSG::rasterizer);

+ 8 - 8
servers/rendering/rendering_server_raster.h → servers/rendering/rendering_server_default.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  rendering_server_raster.h                                            */
+/*  rendering_server_default.h                                           */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,18 +28,18 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef RENDERING_SERVER_RASTER_H
-#define RENDERING_SERVER_RASTER_H
+#ifndef RENDERING_SERVER_DEFAULT_H
+#define RENDERING_SERVER_DEFAULT_H
 
 #include "core/math/octree.h"
 #include "rendering_server_canvas.h"
 #include "rendering_server_globals.h"
-#include "rendering_server_scene.h"
+#include "rendering_server_scene_raster.h"
 #include "rendering_server_viewport.h"
 #include "servers/rendering/rasterizer.h"
 #include "servers/rendering_server.h"
 
-class RenderingServerRaster : public RenderingServer {
+class RenderingServerDefault : public RenderingServer {
 	enum {
 		MAX_INSTANCE_CULL = 8192,
 		MAX_INSTANCE_LIGHTS = 4,
@@ -554,7 +554,7 @@ public:
 
 #undef BINDBASE
 //from now on, calls forwarded to this singleton
-#define BINDBASE RSG::scene_render
+#define BINDBASE RSG::scene
 
 	BIND1(directional_shadow_atlas_set_size, int)
 	BIND1(gi_probe_set_quality, GIProbeQuality)
@@ -853,8 +853,8 @@ public:
 
 	virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
 
-	RenderingServerRaster();
-	~RenderingServerRaster();
+	RenderingServerDefault();
+	~RenderingServerDefault();
 
 #undef DISPLAY_CHANGED
 

+ 0 - 1
servers/rendering/rendering_server_globals.cpp

@@ -32,7 +32,6 @@
 
 RasterizerStorage *RenderingServerGlobals::storage = nullptr;
 RasterizerCanvas *RenderingServerGlobals::canvas_render = nullptr;
-RasterizerScene *RenderingServerGlobals::scene_render = nullptr;
 Rasterizer *RenderingServerGlobals::rasterizer = nullptr;
 
 RenderingServerCanvas *RenderingServerGlobals::canvas = nullptr;

+ 0 - 1
servers/rendering/rendering_server_globals.h

@@ -41,7 +41,6 @@ class RenderingServerGlobals {
 public:
 	static RasterizerStorage *storage;
 	static RasterizerCanvas *canvas_render;
-	static RasterizerScene *scene_render;
 	static Rasterizer *rasterizer;
 
 	static RenderingServerCanvas *canvas;

+ 0 - 3005
servers/rendering/rendering_server_scene.cpp

@@ -30,3012 +30,7 @@
 
 #include "rendering_server_scene.h"
 
-#include "core/os/os.h"
-#include "rendering_server_globals.h"
-#include "rendering_server_raster.h"
-
-#include <new>
-
-/* CAMERA API */
-
-RID RenderingServerScene::camera_create() {
-	Camera *camera = memnew(Camera);
-	return camera_owner.make_rid(camera);
-}
-
-void RenderingServerScene::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-	camera->type = Camera::PERSPECTIVE;
-	camera->fov = p_fovy_degrees;
-	camera->znear = p_z_near;
-	camera->zfar = p_z_far;
-}
-
-void RenderingServerScene::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-	camera->type = Camera::ORTHOGONAL;
-	camera->size = p_size;
-	camera->znear = p_z_near;
-	camera->zfar = p_z_far;
-}
-
-void RenderingServerScene::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-	camera->type = Camera::FRUSTUM;
-	camera->size = p_size;
-	camera->offset = p_offset;
-	camera->znear = p_z_near;
-	camera->zfar = p_z_far;
-}
-
-void RenderingServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-	camera->transform = p_transform.orthonormalized();
-}
-
-void RenderingServerScene::camera_set_cull_mask(RID p_camera, uint32_t p_layers) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-
-	camera->visible_layers = p_layers;
-}
-
-void RenderingServerScene::camera_set_environment(RID p_camera, RID p_env) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-	camera->env = p_env;
-}
-
-void RenderingServerScene::camera_set_camera_effects(RID p_camera, RID p_fx) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-	camera->effects = p_fx;
-}
-
-void RenderingServerScene::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-	camera->vaspect = p_enable;
-}
-
-/* SCENARIO API */
-
-void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int) {
-	//RenderingServerScene *self = (RenderingServerScene*)p_self;
-	Instance *A = p_A;
-	Instance *B = p_B;
-
-	//instance indices are designed so greater always contains lesser
-	if (A->base_type > B->base_type) {
-		SWAP(A, B); //lesser always first
-	}
-
-	if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		InstanceLightData::PairInfo pinfo;
-		pinfo.geometry = A;
-		pinfo.L = geom->lighting.push_back(B);
-
-		List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo);
-
-		if (geom->can_cast_shadows) {
-			light->shadow_dirty = true;
-		}
-		geom->lighting_dirty = true;
-
-		return E; //this element should make freeing faster
-	} else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		InstanceReflectionProbeData::PairInfo pinfo;
-		pinfo.geometry = A;
-		pinfo.L = geom->reflection_probes.push_back(B);
-
-		List<InstanceReflectionProbeData::PairInfo>::Element *E = reflection_probe->geometries.push_back(pinfo);
-
-		geom->reflection_dirty = true;
-
-		return E; //this element should make freeing faster
-	} else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		InstanceDecalData::PairInfo pinfo;
-		pinfo.geometry = A;
-		pinfo.L = geom->decals.push_back(B);
-
-		List<InstanceDecalData::PairInfo>::Element *E = decal->geometries.push_back(pinfo);
-
-		geom->decal_dirty = true;
-
-		return E; //this element should make freeing faster
-	} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		if (A->dynamic_gi) {
-			InstanceLightmapData::PairInfo pinfo;
-			pinfo.geometry = A;
-			pinfo.L = geom->lightmap_captures.push_back(B);
-			List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.push_back(pinfo);
-			((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture
-			return E; //this element should make freeing faster
-		} else {
-			return nullptr;
-		}
-
-	} else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		InstanceGIProbeData::PairInfo pinfo;
-		pinfo.geometry = A;
-		pinfo.L = geom->gi_probes.push_back(B);
-
-		List<InstanceGIProbeData::PairInfo>::Element *E;
-		if (A->dynamic_gi) {
-			E = gi_probe->dynamic_geometries.push_back(pinfo);
-		} else {
-			E = gi_probe->geometries.push_back(pinfo);
-		}
-
-		geom->gi_probes_dirty = true;
-
-		return E; //this element should make freeing faster
-
-	} else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
-		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
-		return gi_probe->lights.insert(A);
-	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
-		RSG::storage->particles_add_collision(A->base, B);
-	}
-
-	return nullptr;
-}
-
-void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *udata) {
-	//RenderingServerScene *self = (RenderingServerScene*)p_self;
-	Instance *A = p_A;
-	Instance *B = p_B;
-
-	//instance indices are designed so greater always contains lesser
-	if (A->base_type > B->base_type) {
-		SWAP(A, B); //lesser always first
-	}
-
-	if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		List<InstanceLightData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightData::PairInfo>::Element *>(udata);
-
-		geom->lighting.erase(E->get().L);
-		light->geometries.erase(E);
-
-		if (geom->can_cast_shadows) {
-			light->shadow_dirty = true;
-		}
-		geom->lighting_dirty = true;
-
-	} else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		List<InstanceReflectionProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceReflectionProbeData::PairInfo>::Element *>(udata);
-
-		geom->reflection_probes.erase(E->get().L);
-		reflection_probe->geometries.erase(E);
-
-		geom->reflection_dirty = true;
-	} else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		List<InstanceDecalData::PairInfo>::Element *E = reinterpret_cast<List<InstanceDecalData::PairInfo>::Element *>(udata);
-
-		geom->decals.erase(E->get().L);
-		decal->geometries.erase(E);
-
-		geom->decal_dirty = true;
-	} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
-		if (udata) { //only for dynamic geometries
-			InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
-			InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-			List<InstanceLightmapData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightmapData::PairInfo>::Element *>(udata);
-
-			geom->lightmap_captures.erase(E->get().L);
-			lightmap_data->geometries.erase(E);
-			((RenderingServerScene *)p_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)) {
-		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
-
-		List<InstanceGIProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceGIProbeData::PairInfo>::Element *>(udata);
-
-		geom->gi_probes.erase(E->get().L);
-		if (A->dynamic_gi) {
-			gi_probe->dynamic_geometries.erase(E);
-		} else {
-			gi_probe->geometries.erase(E);
-		}
-
-		geom->gi_probes_dirty = true;
-
-	} else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
-		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
-		Set<Instance *>::Element *E = reinterpret_cast<Set<Instance *>::Element *>(udata);
-
-		gi_probe->lights.erase(E);
-	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
-		RSG::storage->particles_remove_collision(A->base, B);
-	}
-}
-
-RID RenderingServerScene::scenario_create() {
-	Scenario *scenario = memnew(Scenario);
-	ERR_FAIL_COND_V(!scenario, RID());
-	RID scenario_rid = scenario_owner.make_rid(scenario);
-	scenario->self = scenario_rid;
-
-	scenario->octree.set_pair_callback(_instance_pair, this);
-	scenario->octree.set_unpair_callback(_instance_unpair, this);
-	scenario->reflection_probe_shadow_atlas = RSG::scene_render->shadow_atlas_create();
-	RSG::scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest
-	RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4);
-	RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);
-	RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);
-	RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);
-	scenario->reflection_atlas = RSG::scene_render->reflection_atlas_create();
-	return scenario_rid;
-}
-
-void RenderingServerScene::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) {
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND(!scenario);
-	scenario->debug = p_debug_mode;
-}
-
-void RenderingServerScene::scenario_set_environment(RID p_scenario, RID p_environment) {
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND(!scenario);
-	scenario->environment = p_environment;
-}
-
-void RenderingServerScene::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) {
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND(!scenario);
-	scenario->camera_effects = p_camera_effects;
-}
-
-void RenderingServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND(!scenario);
-	scenario->fallback_environment = p_environment;
-}
-
-void RenderingServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND(!scenario);
-	RSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);
-}
-
-/* INSTANCING API */
-
-void RenderingServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
-	if (p_update_aabb) {
-		p_instance->update_aabb = true;
-	}
-	if (p_update_dependencies) {
-		p_instance->update_dependencies = true;
-	}
-
-	if (p_instance->update_item.in_list()) {
-		return;
-	}
-
-	_instance_update_list.add(&p_instance->update_item);
-}
-
-RID RenderingServerScene::instance_create() {
-	Instance *instance = memnew(Instance);
-	ERR_FAIL_COND_V(!instance, RID());
-
-	RID instance_rid = instance_owner.make_rid(instance);
-	instance->self = instance_rid;
-
-	return instance_rid;
-}
-
-void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	Scenario *scenario = instance->scenario;
-
-	if (instance->base_type != RS::INSTANCE_NONE) {
-		//free anything related to that base
-
-		if (scenario && instance->octree_id) {
-			scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
-			instance->octree_id = 0;
-		}
-
-		switch (instance->base_type) {
-			case RS::INSTANCE_LIGHT: {
-				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
-
-				if (scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
-					scenario->dynamic_lights.erase(light->instance);
-				}
-
-#ifdef DEBUG_ENABLED
-				if (light->geometries.size()) {
-					ERR_PRINT("BUG, indexing did not unpair geometries from light.");
-				}
-#endif
-				if (scenario && light->D) {
-					scenario->directional_lights.erase(light->D);
-					light->D = nullptr;
-				}
-				RSG::scene_render->free(light->instance);
-			} break;
-			case RS::INSTANCE_REFLECTION_PROBE: {
-				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
-				RSG::scene_render->free(reflection_probe->instance);
-				if (reflection_probe->update_list.in_list()) {
-					reflection_probe_render_list.remove(&reflection_probe->update_list);
-				}
-			} break;
-			case RS::INSTANCE_DECAL: {
-				InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);
-				RSG::scene_render->free(decal->instance);
-
-			} break;
-			case RS::INSTANCE_LIGHTMAP: {
-				InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(instance->base_data);
-				//erase dependencies, since no longer a lightmap
-				while (lightmap_data->users.front()) {
-					instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0);
-				}
-			} break;
-			case RS::INSTANCE_GI_PROBE: {
-				InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
-#ifdef DEBUG_ENABLED
-				if (gi_probe->geometries.size()) {
-					ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe.");
-				}
-#endif
-#ifdef DEBUG_ENABLED
-				if (gi_probe->lights.size()) {
-					ERR_PRINT("BUG, indexing did not unpair lights from GIProbe.");
-				}
-#endif
-				if (gi_probe->update_element.in_list()) {
-					gi_probe_update_list.remove(&gi_probe->update_element);
-				}
-
-				RSG::scene_render->free(gi_probe->probe_instance);
-
-			} break;
-			default: {
-			}
-		}
-
-		if (instance->base_data) {
-			memdelete(instance->base_data);
-			instance->base_data = nullptr;
-		}
-
-		instance->blend_values.clear();
-		instance->materials.clear();
-	}
-
-	instance->base_type = RS::INSTANCE_NONE;
-	instance->base = RID();
-
-	if (p_base.is_valid()) {
-		instance->base_type = RSG::storage->get_base_type(p_base);
-		ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE);
-
-		switch (instance->base_type) {
-			case RS::INSTANCE_LIGHT: {
-				InstanceLightData *light = memnew(InstanceLightData);
-
-				if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
-					light->D = scenario->directional_lights.push_back(instance);
-				}
-
-				light->instance = RSG::scene_render->light_instance_create(p_base);
-
-				instance->base_data = light;
-			} break;
-			case RS::INSTANCE_MESH:
-			case RS::INSTANCE_MULTIMESH:
-			case RS::INSTANCE_IMMEDIATE:
-			case RS::INSTANCE_PARTICLES: {
-				InstanceGeometryData *geom = memnew(InstanceGeometryData);
-				instance->base_data = geom;
-				if (instance->base_type == RS::INSTANCE_MESH) {
-					instance->blend_values.resize(RSG::storage->mesh_get_blend_shape_count(p_base));
-				}
-			} break;
-			case RS::INSTANCE_REFLECTION_PROBE: {
-				InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
-				reflection_probe->owner = instance;
-				instance->base_data = reflection_probe;
-
-				reflection_probe->instance = RSG::scene_render->reflection_probe_instance_create(p_base);
-			} break;
-			case RS::INSTANCE_DECAL: {
-				InstanceDecalData *decal = memnew(InstanceDecalData);
-				decal->owner = instance;
-				instance->base_data = decal;
-
-				decal->instance = RSG::scene_render->decal_instance_create(p_base);
-			} break;
-			case RS::INSTANCE_LIGHTMAP: {
-				InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
-				instance->base_data = lightmap_data;
-				//lightmap_data->instance = RSG::scene_render->lightmap_data_instance_create(p_base);
-			} break;
-			case RS::INSTANCE_GI_PROBE: {
-				InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData);
-				instance->base_data = gi_probe;
-				gi_probe->owner = instance;
-
-				if (scenario && !gi_probe->update_element.in_list()) {
-					gi_probe_update_list.add(&gi_probe->update_element);
-				}
-
-				gi_probe->probe_instance = RSG::scene_render->gi_probe_instance_create(p_base);
-
-			} break;
-			default: {
-			}
-		}
-
-		instance->base = p_base;
-
-		//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
-		RSG::storage->base_update_dependency(p_base, instance);
-	}
-
-	_instance_queue_update(instance, true, true);
-}
-
-void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	if (instance->scenario) {
-		instance->scenario->instances.remove(&instance->scenario_item);
-
-		if (instance->octree_id) {
-			instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
-			instance->octree_id = 0;
-		}
-
-		switch (instance->base_type) {
-			case RS::INSTANCE_LIGHT: {
-				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
-#ifdef DEBUG_ENABLED
-				if (light->geometries.size()) {
-					ERR_PRINT("BUG, indexing did not unpair geometries from light.");
-				}
-#endif
-				if (light->D) {
-					instance->scenario->directional_lights.erase(light->D);
-					light->D = nullptr;
-				}
-			} break;
-			case RS::INSTANCE_REFLECTION_PROBE: {
-				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
-				RSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
-
-			} break;
-			case RS::INSTANCE_PARTICLES_COLLISION: {
-				heightfield_particle_colliders_update_list.erase(instance);
-			} break;
-			case RS::INSTANCE_GI_PROBE: {
-				InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
-
-#ifdef DEBUG_ENABLED
-				if (gi_probe->geometries.size()) {
-					ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe.");
-				}
-#endif
-#ifdef DEBUG_ENABLED
-				if (gi_probe->lights.size()) {
-					ERR_PRINT("BUG, indexing did not unpair lights from GIProbe.");
-				}
-#endif
-
-				if (gi_probe->update_element.in_list()) {
-					gi_probe_update_list.remove(&gi_probe->update_element);
-				}
-			} break;
-			default: {
-			}
-		}
-
-		instance->scenario = nullptr;
-	}
-
-	if (p_scenario.is_valid()) {
-		Scenario *scenario = scenario_owner.getornull(p_scenario);
-		ERR_FAIL_COND(!scenario);
-
-		instance->scenario = scenario;
-
-		scenario->instances.add(&instance->scenario_item);
-
-		switch (instance->base_type) {
-			case RS::INSTANCE_LIGHT: {
-				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
-
-				if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
-					light->D = scenario->directional_lights.push_back(instance);
-				}
-			} break;
-			case RS::INSTANCE_GI_PROBE: {
-				InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
-				if (!gi_probe->update_element.in_list()) {
-					gi_probe_update_list.add(&gi_probe->update_element);
-				}
-			} break;
-			default: {
-			}
-		}
-
-		_instance_queue_update(instance, true, true);
-	}
-}
-
-void RenderingServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	instance->layer_mask = p_mask;
-}
-
-void RenderingServerScene::instance_set_transform(RID p_instance, const Transform &p_transform) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	if (instance->transform == p_transform) {
-		return; //must be checked to avoid worst evil
-	}
-
-#ifdef DEBUG_ENABLED
-
-	for (int i = 0; i < 4; i++) {
-		const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin;
-		ERR_FAIL_COND(Math::is_inf(v.x));
-		ERR_FAIL_COND(Math::is_nan(v.x));
-		ERR_FAIL_COND(Math::is_inf(v.y));
-		ERR_FAIL_COND(Math::is_nan(v.y));
-		ERR_FAIL_COND(Math::is_inf(v.z));
-		ERR_FAIL_COND(Math::is_nan(v.z));
-	}
-
-#endif
-	instance->transform = p_transform;
-	_instance_queue_update(instance, true);
-}
-
-void RenderingServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	instance->object_id = p_id;
-}
-
-void RenderingServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	if (instance->update_item.in_list()) {
-		_update_dirty_instance(instance);
-	}
-
-	ERR_FAIL_INDEX(p_shape, instance->blend_values.size());
-	instance->blend_values.write[p_shape] = p_weight;
-}
-
-void RenderingServerScene::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	if (instance->base_type == RS::INSTANCE_MESH) {
-		//may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case
-		instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base)));
-	}
-
-	ERR_FAIL_INDEX(p_surface, instance->materials.size());
-
-	instance->materials.write[p_surface] = p_material;
-
-	_instance_queue_update(instance, false, true);
-}
-
-void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	if (instance->visible == p_visible) {
-		return;
-	}
-
-	instance->visible = p_visible;
-
-	switch (instance->base_type) {
-		case RS::INSTANCE_LIGHT: {
-			if (RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) {
-				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHT, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
-			}
-
-		} break;
-		case RS::INSTANCE_REFLECTION_PROBE: {
-			if (instance->octree_id && instance->scenario) {
-				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
-			}
-
-		} break;
-		case RS::INSTANCE_DECAL: {
-			if (instance->octree_id && instance->scenario) {
-				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_DECAL, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
-			}
-
-		} break;
-		case RS::INSTANCE_LIGHTMAP: {
-			if (instance->octree_id && instance->scenario) {
-				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
-			}
-
-		} break;
-		case RS::INSTANCE_GI_PROBE: {
-			if (instance->octree_id && instance->scenario) {
-				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_GI_PROBE, p_visible ? (RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT)) : 0);
-			}
-
-		} break;
-		case RS::INSTANCE_PARTICLES_COLLISION: {
-			if (instance->octree_id && instance->scenario) {
-				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_PARTICLES_COLLISION, p_visible ? (1 << RS::INSTANCE_PARTICLES) : 0);
-			}
-
-		} break;
-		default: {
-		}
-	}
-}
-
-inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
-	return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE;
-}
-
-void RenderingServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-	ERR_FAIL_COND(!is_geometry_instance(instance->base_type));
-
-	if (p_aabb != AABB()) {
-		// Set custom AABB
-		if (instance->custom_aabb == nullptr) {
-			instance->custom_aabb = memnew(AABB);
-		}
-		*instance->custom_aabb = p_aabb;
-
-	} else {
-		// Clear custom AABB
-		if (instance->custom_aabb != nullptr) {
-			memdelete(instance->custom_aabb);
-			instance->custom_aabb = nullptr;
-		}
-	}
-
-	if (instance->scenario) {
-		_instance_queue_update(instance, true, false);
-	}
-}
-
-void RenderingServerScene::instance_attach_skeleton(RID p_instance, RID p_skeleton) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	if (instance->skeleton == p_skeleton) {
-		return;
-	}
-
-	instance->skeleton = p_skeleton;
-
-	if (p_skeleton.is_valid()) {
-		//update the dependency now, so if cleared, we remove it
-		RSG::storage->skeleton_update_dependency(p_skeleton, instance);
-	}
-	_instance_queue_update(instance, true, true);
-}
-
-void RenderingServerScene::instance_set_exterior(RID p_instance, bool p_enabled) {
-}
-
-void RenderingServerScene::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	instance->extra_margin = p_margin;
-	_instance_queue_update(instance, true, false);
-}
-
-Vector<ObjectID> RenderingServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
-	Vector<ObjectID> instances;
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND_V(!scenario, instances);
-
-	const_cast<RenderingServerScene *>(this)->update_dirty_instances(); // check dirty instances before culling
-
-	int culled = 0;
-	Instance *cull[1024];
-	culled = scenario->octree.cull_aabb(p_aabb, cull, 1024);
-
-	for (int i = 0; i < culled; i++) {
-		Instance *instance = cull[i];
-		ERR_CONTINUE(!instance);
-		if (instance->object_id.is_null()) {
-			continue;
-		}
-
-		instances.push_back(instance->object_id);
-	}
-
-	return instances;
-}
-
-Vector<ObjectID> RenderingServerScene::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
-	Vector<ObjectID> instances;
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND_V(!scenario, instances);
-	const_cast<RenderingServerScene *>(this)->update_dirty_instances(); // check dirty instances before culling
-
-	int culled = 0;
-	Instance *cull[1024];
-	culled = scenario->octree.cull_segment(p_from, p_from + p_to * 10000, cull, 1024);
-
-	for (int i = 0; i < culled; i++) {
-		Instance *instance = cull[i];
-		ERR_CONTINUE(!instance);
-		if (instance->object_id.is_null()) {
-			continue;
-		}
-
-		instances.push_back(instance->object_id);
-	}
-
-	return instances;
-}
-
-Vector<ObjectID> RenderingServerScene::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const {
-	Vector<ObjectID> instances;
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND_V(!scenario, instances);
-	const_cast<RenderingServerScene *>(this)->update_dirty_instances(); // check dirty instances before culling
-
-	int culled = 0;
-	Instance *cull[1024];
-
-	culled = scenario->octree.cull_convex(p_convex, cull, 1024);
-
-	for (int i = 0; i < culled; i++) {
-		Instance *instance = cull[i];
-		ERR_CONTINUE(!instance);
-		if (instance->object_id.is_null()) {
-			continue;
-		}
-
-		instances.push_back(instance->object_id);
-	}
-
-	return instances;
-}
-
-void RenderingServerScene::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	//ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK));
-
-	switch (p_flags) {
-		case RS::INSTANCE_FLAG_USE_BAKED_LIGHT: {
-			instance->baked_light = p_enabled;
-
-		} break;
-		case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: {
-			if (p_enabled == instance->dynamic_gi) {
-				//bye, redundant
-				return;
-			}
-
-			if (instance->octree_id != 0) {
-				//remove from octree, it needs to be re-paired
-				instance->scenario->octree.erase(instance->octree_id);
-				instance->octree_id = 0;
-				_instance_queue_update(instance, true, true);
-			}
-
-			//once out of octree, can be changed
-			instance->dynamic_gi = p_enabled;
-
-		} break;
-		case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {
-			instance->redraw_if_visible = p_enabled;
-
-		} break;
-		default: {
-		}
-	}
-}
-
-void RenderingServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	instance->cast_shadows = p_shadow_casting_setting;
-	_instance_queue_update(instance, false, true);
-}
-
-void RenderingServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	instance->material_override = p_material;
-	_instance_queue_update(instance, false, true);
-}
-
-void RenderingServerScene::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
-}
-
-void RenderingServerScene::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) {
-}
-
-void RenderingServerScene::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	if (instance->lightmap) {
-		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(((Instance *)instance->lightmap)->base_data);
-		lightmap_data->users.erase(instance);
-		instance->lightmap = nullptr;
-	}
-
-	Instance *lightmap_instance = instance_owner.getornull(p_lightmap);
-
-	instance->lightmap = lightmap_instance;
-	instance->lightmap_uv_scale = p_lightmap_uv_scale;
-	instance->lightmap_slice_index = p_slice_index;
-
-	if (lightmap_instance) {
-		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data);
-		lightmap_data->users.insert(instance);
-	}
-}
-
-void RenderingServerScene::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
-	Instance *instance = instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
-
-	if (!E) {
-		RasterizerScene::InstanceBase::InstanceShaderParameter isp;
-		isp.index = -1;
-		isp.info = PropertyInfo();
-		isp.value = p_value;
-		instance->instance_shader_parameters[p_parameter] = isp;
-	} else {
-		E->get().value = p_value;
-		if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) {
-			//update directly
-			RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value);
-		}
-	}
-}
-
-Variant RenderingServerScene::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {
-	const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
-	ERR_FAIL_COND_V(!instance, Variant());
-
-	if (instance->instance_shader_parameters.has(p_parameter)) {
-		return instance->instance_shader_parameters[p_parameter].value;
-	}
-	return Variant();
-}
-
-Variant RenderingServerScene::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {
-	const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
-	ERR_FAIL_COND_V(!instance, Variant());
-
-	if (instance->instance_shader_parameters.has(p_parameter)) {
-		return instance->instance_shader_parameters[p_parameter].default_value;
-	}
-	return Variant();
-}
-
-void RenderingServerScene::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
-	const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance);
-	ERR_FAIL_COND(!instance);
-
-	const_cast<RenderingServerScene *>(this)->update_dirty_instances();
-
-	Vector<StringName> names;
-	for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
-		names.push_back(E->key());
-	}
-	names.sort_custom<StringName::AlphCompare>();
-	for (int i = 0; i < names.size(); i++) {
-		PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info;
-		p_parameters->push_back(pinfo);
-	}
-}
-
-void RenderingServerScene::_update_instance(Instance *p_instance) {
-	p_instance->version++;
-
-	if (p_instance->base_type == RS::INSTANCE_LIGHT) {
-		InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
-
-		RSG::scene_render->light_instance_set_transform(light->instance, p_instance->transform);
-		RSG::scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb));
-		light->shadow_dirty = true;
-
-		RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base);
-		if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
-			if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
-				p_instance->scenario->dynamic_lights.erase(light->instance);
-			}
-
-			light->bake_mode = bake_mode;
-
-			if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
-				p_instance->scenario->dynamic_lights.push_back(light->instance);
-			}
-		}
-
-		uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base);
-		if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
-			light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
-		}
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
-		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
-
-		RSG::scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform);
-		reflection_probe->reflection_dirty = true;
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_DECAL) {
-		InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
-
-		RSG::scene_render->decal_instance_set_transform(decal->instance, p_instance->transform);
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
-		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data);
-
-		RSG::scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform);
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
-		RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
-	}
-
-	if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
-		//remove materials no longer used and un-own them
-		if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) {
-			heightfield_particle_colliders_update_list.insert(p_instance);
-		}
-	}
-
-	if (p_instance->aabb.has_no_surface()) {
-		return;
-	}
-
-	if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
-		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
-		//make sure lights are updated if it casts shadow
-
-		if (geom->can_cast_shadows) {
-			for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
-				InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
-				light->shadow_dirty = true;
-			}
-		}
-
-		if (!p_instance->lightmap && geom->lightmap_captures.size()) {
-			//affected by lightmap captures, must update capture info!
-			_update_instance_lightmap_captures(p_instance);
-		} else {
-			if (!p_instance->lightmap_sh.empty()) {
-				p_instance->lightmap_sh.clear(); //don't need SH
-				p_instance->lightmap_target_sh.clear(); //don't need SH
-			}
-		}
-	}
-
-	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 (List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
-			Instance *geom = E->get().geometry;
-			_instance_queue_update(geom, true, false);
-		}
-	}
-
-	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) {
-		return;
-	}
-
-	if (p_instance->octree_id == 0) {
-		uint32_t base_type = 1 << p_instance->base_type;
-		uint32_t pairable_mask = 0;
-		bool pairable = false;
-
-		if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL || p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
-			pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
-			pairable = true;
-		}
-
-		if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
-			pairable_mask = p_instance->visible ? (1 << RS::INSTANCE_PARTICLES) : 0;
-			pairable = true;
-		}
-
-		if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
-			//lights and geometries
-			pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT) : 0;
-			pairable = true;
-		}
-
-		// not inside octree
-		p_instance->octree_id = p_instance->scenario->octree.create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask);
-
-	} else {
-		/*
-		if (new_aabb==p_instance->data.transformed_aabb)
-			return;
-		*/
-
-		p_instance->scenario->octree.move(p_instance->octree_id, new_aabb);
-	}
-}
-
-void RenderingServerScene::_update_instance_aabb(Instance *p_instance) {
-	AABB new_aabb;
-
-	ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_NONE && !p_instance->base.is_valid());
-
-	switch (p_instance->base_type) {
-		case RenderingServer::INSTANCE_NONE: {
-			// do nothing
-		} break;
-		case RenderingServer::INSTANCE_MESH: {
-			if (p_instance->custom_aabb) {
-				new_aabb = *p_instance->custom_aabb;
-			} else {
-				new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
-			}
-
-		} break;
-
-		case RenderingServer::INSTANCE_MULTIMESH: {
-			if (p_instance->custom_aabb) {
-				new_aabb = *p_instance->custom_aabb;
-			} else {
-				new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base);
-			}
-
-		} break;
-		case RenderingServer::INSTANCE_IMMEDIATE: {
-			if (p_instance->custom_aabb) {
-				new_aabb = *p_instance->custom_aabb;
-			} else {
-				new_aabb = RSG::storage->immediate_get_aabb(p_instance->base);
-			}
-
-		} break;
-		case RenderingServer::INSTANCE_PARTICLES: {
-			if (p_instance->custom_aabb) {
-				new_aabb = *p_instance->custom_aabb;
-			} else {
-				new_aabb = RSG::storage->particles_get_aabb(p_instance->base);
-			}
-
-		} break;
-		case RenderingServer::INSTANCE_PARTICLES_COLLISION: {
-			new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
-
-		} break;
-		case RenderingServer::INSTANCE_LIGHT: {
-			new_aabb = RSG::storage->light_get_aabb(p_instance->base);
-
-		} break;
-		case RenderingServer::INSTANCE_REFLECTION_PROBE: {
-			new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
-
-		} break;
-		case RenderingServer::INSTANCE_DECAL: {
-			new_aabb = RSG::storage->decal_get_aabb(p_instance->base);
-
-		} break;
-		case RenderingServer::INSTANCE_GI_PROBE: {
-			new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base);
-
-		} break;
-		case RenderingServer::INSTANCE_LIGHTMAP: {
-			new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base);
-
-		} break;
-		default: {
-		}
-	}
-
-	// <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs
-	if (p_instance->extra_margin) {
-		new_aabb.grow_by(p_instance->extra_margin);
-	}
-
-	p_instance->aabb = new_aabb;
-}
-
-void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instance) {
-	bool first_set = p_instance->lightmap_sh.size() == 0;
-	p_instance->lightmap_sh.resize(9); //using SH
-	p_instance->lightmap_target_sh.resize(9); //using SH
-	Color *instance_sh = p_instance->lightmap_target_sh.ptrw();
-	bool inside = false;
-	Color accum_sh[9];
-	float accum_blend = 0.0;
-
-	InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
-	for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
-		Instance *lightmap = E->get();
-
-		bool interior = RSG::storage->lightmap_is_interior(lightmap->base);
-
-		if (inside && !interior) {
-			continue; //we are inside, ignore exteriors
-		}
-
-		Transform to_bounds = lightmap->transform.affine_inverse();
-		Vector3 center = p_instance->transform.xform(p_instance->aabb.position + p_instance->aabb.size * 0.5); //use aabb center
-
-		Vector3 lm_pos = to_bounds.xform(center);
-
-		AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base);
-		if (!bounds.has_point(lm_pos)) {
-			continue; //not in this lightmap
-		}
-
-		Color sh[9];
-		RSG::storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);
-
-		//rotate it
-		Basis rot = lightmap->transform.basis.orthonormalized();
-		for (int i = 0; i < 3; i++) {
-			float csh[9];
-			for (int j = 0; j < 9; j++) {
-				csh[j] = sh[j][i];
-			}
-			rot.rotate_sh(csh);
-			for (int j = 0; j < 9; j++) {
-				sh[j][i] = csh[j];
-			}
-		}
-
-		Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0);
-
-		float blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z));
-		//make blend more rounded
-		blend = Math::lerp(inner_pos.length(), blend, blend);
-		blend *= blend;
-		blend = MAX(0.0, 1.0 - blend);
-
-		if (interior && !inside) {
-			//do not blend, just replace
-			for (int j = 0; j < 9; j++) {
-				accum_sh[j] = sh[j] * blend;
-			}
-			accum_blend = blend;
-			inside = true;
-		} else {
-			for (int j = 0; j < 9; j++) {
-				accum_sh[j] += sh[j] * blend;
-			}
-			accum_blend += blend;
-		}
-	}
-
-	if (accum_blend > 0.0) {
-		for (int j = 0; j < 9; j++) {
-			instance_sh[j] = accum_sh[j] / accum_blend;
-			if (first_set) {
-				p_instance->lightmap_sh.write[j] = instance_sh[j];
-			}
-		}
-	}
-}
-
-bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario) {
-	InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
-
-	Transform light_transform = p_instance->transform;
-	light_transform.orthonormalize(); //scale does not count on lights
-
-	bool animated_material_found = false;
-
-	switch (RSG::storage->light_get_type(p_instance->base)) {
-		case RS::LIGHT_DIRECTIONAL: {
-			real_t max_distance = p_cam_projection.get_z_far();
-			real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
-			if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
-				max_distance = MIN(shadow_max, max_distance);
-			}
-			max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
-			real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
-
-			RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
-
-			real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
-
-			if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) {
-				//optimize min/max
-				Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
-				int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
-				Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2));
-				//check distance max and min
-
-				bool found_items = false;
-				real_t z_max = -1e20;
-				real_t z_min = 1e20;
-
-				for (int i = 0; i < cull_count; i++) {
-					Instance *instance = instance_shadow_cull_result[i];
-					if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
-						continue;
-					}
-
-					if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
-						animated_material_found = true;
-					}
-
-					real_t max, min;
-					instance->transformed_aabb.project_range_in_plane(base, min, max);
-
-					if (max > z_max) {
-						z_max = max;
-					}
-
-					if (min < z_min) {
-						z_min = min;
-					}
-
-					found_items = true;
-				}
-
-				if (found_items) {
-					min_distance = MAX(min_distance, z_min);
-					max_distance = MIN(max_distance, z_max);
-				}
-			}
-
-			real_t range = max_distance - min_distance;
-
-			int splits = 0;
-			switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
-				case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
-					splits = 1;
-					break;
-				case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
-					splits = 2;
-					break;
-				case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
-					splits = 4;
-					break;
-			}
-
-			real_t distances[5];
-
-			distances[0] = min_distance;
-			for (int i = 0; i < splits; i++) {
-				distances[i + 1] = min_distance + RSG::storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
-			};
-
-			distances[splits] = max_distance;
-
-			real_t texture_size = RSG::scene_render->get_directional_light_shadow_size(light->instance);
-
-			bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
-
-			real_t first_radius = 0.0;
-
-			real_t min_distance_bias_scale = pancake_size > 0 ? distances[1] / 10.0 : 0;
-
-			for (int i = 0; i < splits; i++) {
-				RENDER_TIMESTAMP("Culling Directional Light split" + itos(i));
-
-				// setup a camera matrix for that range!
-				CameraMatrix camera_matrix;
-
-				real_t aspect = p_cam_projection.get_aspect();
-
-				if (p_cam_orthogonal) {
-					Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
-
-					camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
-				} else {
-					real_t fov = p_cam_projection.get_fov(); //this is actually yfov, because set aspect tries to keep it
-					camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
-				}
-
-				//obtain the frustum endpoints
-
-				Vector3 endpoints[8]; // frustum plane endpoints
-				bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints);
-				ERR_CONTINUE(!res);
-
-				// obtain the light frustm ranges (given endpoints)
-
-				Transform transform = light_transform; //discard scale and stabilize light
-
-				Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized();
-				Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized();
-				Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized();
-				//z_vec points agsint the camera, like in default opengl
-
-				real_t x_min = 0.f, x_max = 0.f;
-				real_t y_min = 0.f, y_max = 0.f;
-				real_t z_min = 0.f, z_max = 0.f;
-
-				// FIXME: z_max_cam is defined, computed, but not used below when setting up
-				// ortho_camera. Commented out for now to fix warnings but should be investigated.
-				real_t x_min_cam = 0.f, x_max_cam = 0.f;
-				real_t y_min_cam = 0.f, y_max_cam = 0.f;
-				real_t z_min_cam = 0.f;
-				//real_t z_max_cam = 0.f;
-
-				real_t bias_scale = 1.0;
-				real_t aspect_bias_scale = 1.0;
-
-				//used for culling
-
-				for (int j = 0; j < 8; j++) {
-					real_t d_x = x_vec.dot(endpoints[j]);
-					real_t d_y = y_vec.dot(endpoints[j]);
-					real_t d_z = z_vec.dot(endpoints[j]);
-
-					if (j == 0 || d_x < x_min) {
-						x_min = d_x;
-					}
-					if (j == 0 || d_x > x_max) {
-						x_max = d_x;
-					}
-
-					if (j == 0 || d_y < y_min) {
-						y_min = d_y;
-					}
-					if (j == 0 || d_y > y_max) {
-						y_max = d_y;
-					}
-
-					if (j == 0 || d_z < z_min) {
-						z_min = d_z;
-					}
-					if (j == 0 || d_z > z_max) {
-						z_max = d_z;
-					}
-				}
-
-				real_t radius = 0;
-				real_t soft_shadow_expand = 0;
-				Vector3 center;
-
-				{
-					//camera viewport stuff
-
-					for (int j = 0; j < 8; j++) {
-						center += endpoints[j];
-					}
-					center /= 8.0;
-
-					//center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;
-
-					for (int j = 0; j < 8; j++) {
-						real_t d = center.distance_to(endpoints[j]);
-						if (d > radius) {
-							radius = d;
-						}
-					}
-
-					radius *= texture_size / (texture_size - 2.0); //add a texel by each side
-
-					if (i == 0) {
-						first_radius = radius;
-					} else {
-						bias_scale = radius / first_radius;
-					}
-
-					z_min_cam = z_vec.dot(center) - radius;
-
-					{
-						float soft_shadow_angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);
-
-						if (soft_shadow_angle > 0.0 && pancake_size > 0.0) {
-							float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;
-							soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range;
-
-							x_max += soft_shadow_expand;
-							y_max += soft_shadow_expand;
-
-							x_min -= soft_shadow_expand;
-							y_min -= soft_shadow_expand;
-						}
-					}
-
-					x_max_cam = x_vec.dot(center) + radius + soft_shadow_expand;
-					x_min_cam = x_vec.dot(center) - radius - soft_shadow_expand;
-					y_max_cam = y_vec.dot(center) + radius + soft_shadow_expand;
-					y_min_cam = y_vec.dot(center) - radius - soft_shadow_expand;
-
-					if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
-						//this trick here is what stabilizes the shadow (make potential jaggies to not move)
-						//at the cost of some wasted resolution. Still the quality increase is very well worth it
-
-						real_t unit = radius * 2.0 / texture_size;
-
-						x_max_cam = Math::stepify(x_max_cam, unit);
-						x_min_cam = Math::stepify(x_min_cam, unit);
-						y_max_cam = Math::stepify(y_max_cam, unit);
-						y_min_cam = Math::stepify(y_min_cam, unit);
-					}
-				}
-
-				//now that we now all ranges, we can proceed to make the light frustum planes, for culling octree
-
-				Vector<Plane> light_frustum_planes;
-				light_frustum_planes.resize(6);
-
-				//right/left
-				light_frustum_planes.write[0] = Plane(x_vec, x_max);
-				light_frustum_planes.write[1] = Plane(-x_vec, -x_min);
-				//top/bottom
-				light_frustum_planes.write[2] = Plane(y_vec, y_max);
-				light_frustum_planes.write[3] = Plane(-y_vec, -y_min);
-				//near/far
-				light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6);
-				light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed
-
-				int cull_count = p_scenario->octree.cull_convex(light_frustum_planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
-
-				// a pre pass will need to be needed to determine the actual z-near to be used
-
-				Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
-
-				real_t cull_max = 0;
-				for (int j = 0; j < cull_count; j++) {
-					real_t min, max;
-					Instance *instance = instance_shadow_cull_result[j];
-					if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
-						cull_count--;
-						SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
-						j--;
-						continue;
-					}
-
-					instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max);
-					instance->depth = near_plane.distance_to(instance->transform.origin);
-					instance->depth_layer = 0;
-					if (j == 0 || max > cull_max) {
-						cull_max = max;
-					}
-				}
-
-				if (cull_max > z_max) {
-					z_max = cull_max;
-				}
-
-				if (pancake_size > 0) {
-					z_max = z_vec.dot(center) + radius + pancake_size;
-				}
-
-				if (aspect != 1.0) {
-					// if the aspect is different, then the radius will become larger.
-					// if this happens, then bias needs to be adjusted too, as depth will increase
-					// to do this, compare the depth of one that would have resulted from a square frustum
-
-					CameraMatrix camera_matrix_square;
-					if (p_cam_orthogonal) {
-						Vector2 vp_he = camera_matrix.get_viewport_half_extents();
-						if (p_cam_vaspect) {
-							camera_matrix_square.set_orthogonal(vp_he.x * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
-						} else {
-							camera_matrix_square.set_orthogonal(vp_he.y * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
-						}
-					} else {
-						Vector2 vp_he = camera_matrix.get_viewport_half_extents();
-						if (p_cam_vaspect) {
-							camera_matrix_square.set_frustum(vp_he.x * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
-						} else {
-							camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
-						}
-					}
-
-					Vector3 endpoints_square[8]; // frustum plane endpoints
-					res = camera_matrix_square.get_endpoints(p_cam_transform, endpoints_square);
-					ERR_CONTINUE(!res);
-					Vector3 center_square;
-					real_t z_max_square = 0;
-
-					for (int j = 0; j < 8; j++) {
-						center_square += endpoints_square[j];
-
-						real_t d_z = z_vec.dot(endpoints_square[j]);
-
-						if (j == 0 || d_z > z_max_square) {
-							z_max_square = d_z;
-						}
-					}
-
-					if (cull_max > z_max_square) {
-						z_max_square = cull_max;
-					}
-
-					center_square /= 8.0;
-
-					real_t radius_square = 0;
-
-					for (int j = 0; j < 8; j++) {
-						real_t d = center_square.distance_to(endpoints_square[j]);
-						if (d > radius_square) {
-							radius_square = d;
-						}
-					}
-
-					radius_square *= texture_size / (texture_size - 2.0); //add a texel by each side
-
-					if (pancake_size > 0) {
-						z_max_square = z_vec.dot(center_square) + radius_square + pancake_size;
-					}
-
-					real_t z_min_cam_square = z_vec.dot(center_square) - radius_square;
-
-					aspect_bias_scale = (z_max - z_min_cam) / (z_max_square - z_min_cam_square);
-
-					// this is not entirely perfect, because the cull-adjusted z-max may be different
-					// but at least it's warranted that it results in a greater bias, so no acne should be present either way.
-					// pancaking also helps with this.
-				}
-
-				{
-					CameraMatrix ortho_camera;
-					real_t half_x = (x_max_cam - x_min_cam) * 0.5;
-					real_t half_y = (y_max_cam - y_min_cam) * 0.5;
-
-					ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam));
-
-					Vector2 uv_scale(1.0 / (x_max_cam - x_min_cam), 1.0 / (y_max_cam - y_min_cam));
-
-					Transform ortho_transform;
-					ortho_transform.basis = transform.basis;
-					ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;
-
-					{
-						Vector3 max_in_view = p_cam_transform.affine_inverse().xform(z_vec * cull_max);
-						Vector3 dir_in_view = p_cam_transform.xform_inv(z_vec).normalized();
-						cull_max = dir_in_view.dot(max_in_view);
-					}
-
-					RSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, z_max - z_min_cam, distances[i + 1], i, radius * 2.0 / texture_size, bias_scale * aspect_bias_scale * min_distance_bias_scale, z_max, uv_scale);
-				}
-
-				RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
-			}
-
-		} break;
-		case RS::LIGHT_OMNI: {
-			RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base);
-
-			if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::scene_render->light_instances_can_render_shadow_cube()) {
-				for (int i = 0; i < 2; i++) {
-					//using this one ensures that raster deferred will have it
-					RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i));
-
-					real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
-
-					real_t z = i == 0 ? -1 : 1;
-					Vector<Plane> planes;
-					planes.resize(6);
-					planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
-					planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
-					planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
-					planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
-					planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
-					planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0));
-
-					int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
-					Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
-
-					for (int j = 0; j < cull_count; j++) {
-						Instance *instance = instance_shadow_cull_result[j];
-						if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
-							cull_count--;
-							SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
-							j--;
-						} else {
-							if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
-								animated_material_found = true;
-							}
-
-							instance->depth = near_plane.distance_to(instance->transform.origin);
-							instance->depth_layer = 0;
-						}
-					}
-
-					RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
-					RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
-				}
-			} else { //shadow cube
-
-				real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
-				CameraMatrix cm;
-				cm.set_perspective(90, 1, 0.01, radius);
-
-				for (int i = 0; i < 6; i++) {
-					RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i));
-					//using this one ensures that raster deferred will have it
-
-					static const Vector3 view_normals[6] = {
-						Vector3(+1, 0, 0),
-						Vector3(-1, 0, 0),
-						Vector3(0, -1, 0),
-						Vector3(0, +1, 0),
-						Vector3(0, 0, +1),
-						Vector3(0, 0, -1)
-					};
-					static const Vector3 view_up[6] = {
-						Vector3(0, -1, 0),
-						Vector3(0, -1, 0),
-						Vector3(0, 0, -1),
-						Vector3(0, 0, +1),
-						Vector3(0, -1, 0),
-						Vector3(0, -1, 0)
-					};
-
-					Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
-
-					Vector<Plane> planes = cm.get_projection_planes(xform);
-
-					int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
-
-					Plane near_plane(xform.origin, -xform.basis.get_axis(2));
-					for (int j = 0; j < cull_count; j++) {
-						Instance *instance = instance_shadow_cull_result[j];
-						if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
-							cull_count--;
-							SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
-							j--;
-						} else {
-							if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
-								animated_material_found = true;
-							}
-							instance->depth = near_plane.distance_to(instance->transform.origin);
-							instance->depth_layer = 0;
-						}
-					}
-
-					RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
-					RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
-				}
-
-				//restore the regular DP matrix
-				RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
-			}
-
-		} break;
-		case RS::LIGHT_SPOT: {
-			RENDER_TIMESTAMP("Culling Spot Light");
-
-			real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
-			real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
-
-			CameraMatrix cm;
-			cm.set_perspective(angle * 2.0, 1.0, 0.01, radius);
-
-			Vector<Plane> planes = cm.get_projection_planes(light_transform);
-			int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
-
-			Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
-			for (int j = 0; j < cull_count; j++) {
-				Instance *instance = instance_shadow_cull_result[j];
-				if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
-					cull_count--;
-					SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
-					j--;
-				} else {
-					if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
-						animated_material_found = true;
-					}
-					instance->depth = near_plane.distance_to(instance->transform.origin);
-					instance->depth_layer = 0;
-				}
-			}
-
-			RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
-			RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
-
-		} break;
-	}
-
-	return animated_material_found;
-}
-
-void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
-// render to mono camera
-#ifndef _3D_DISABLED
-
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-
-	/* STEP 1 - SETUP CAMERA */
-	CameraMatrix camera_matrix;
-	bool ortho = false;
-
-	switch (camera->type) {
-		case Camera::ORTHOGONAL: {
-			camera_matrix.set_orthogonal(
-					camera->size,
-					p_viewport_size.width / (float)p_viewport_size.height,
-					camera->znear,
-					camera->zfar,
-					camera->vaspect);
-			ortho = true;
-		} break;
-		case Camera::PERSPECTIVE: {
-			camera_matrix.set_perspective(
-					camera->fov,
-					p_viewport_size.width / (float)p_viewport_size.height,
-					camera->znear,
-					camera->zfar,
-					camera->vaspect);
-			ortho = false;
-
-		} break;
-		case Camera::FRUSTUM: {
-			camera_matrix.set_frustum(
-					camera->size,
-					p_viewport_size.width / (float)p_viewport_size.height,
-					camera->offset,
-					camera->znear,
-					camera->zfar,
-					camera->vaspect);
-			ortho = false;
-		} break;
-	}
-
-	RID environment = _render_get_environment(p_camera, p_scenario);
-
-	_prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
-	_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
-#endif
-}
-
-void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
-	// render for AR/VR interface
-
-	Camera *camera = camera_owner.getornull(p_camera);
-	ERR_FAIL_COND(!camera);
-
-	/* SETUP CAMERA, we are ignoring type and FOV here */
-	float aspect = p_viewport_size.width / (float)p_viewport_size.height;
-	CameraMatrix camera_matrix = p_interface->get_projection_for_eye(p_eye, aspect, camera->znear, camera->zfar);
-
-	// We also ignore our camera position, it will have been positioned with a slightly old tracking position.
-	// Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo!
-	Transform world_origin = XRServer::get_singleton()->get_world_origin();
-	Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin);
-
-	RID environment = _render_get_environment(p_camera, p_scenario);
-
-	// For stereo render we only prepare for our left eye and then reuse the outcome for our right eye
-	if (p_eye == XRInterface::EYE_LEFT) {
-		// Center our transform, we assume basis is equal.
-		Transform mono_transform = cam_transform;
-		Transform right_transform = p_interface->get_transform_for_eye(XRInterface::EYE_RIGHT, world_origin);
-		mono_transform.origin += right_transform.origin;
-		mono_transform.origin *= 0.5;
-
-		// We need to combine our projection frustums for culling.
-		// Ideally we should use our clipping planes for this and combine them,
-		// however our shadow map logic uses our projection matrix.
-		// Note: as our left and right frustums should be mirrored, we don't need our right projection matrix.
-
-		// - get some base values we need
-		float eye_dist = (mono_transform.origin - cam_transform.origin).length();
-		float z_near = camera_matrix.get_z_near(); // get our near plane
-		float z_far = camera_matrix.get_z_far(); // get our far plane
-		float width = (2.0 * z_near) / camera_matrix.matrix[0][0];
-		float x_shift = width * camera_matrix.matrix[2][0];
-		float height = (2.0 * z_near) / camera_matrix.matrix[1][1];
-		float y_shift = height * camera_matrix.matrix[2][1];
-
-		// printf("Eye_dist = %f, Near = %f, Far = %f, Width = %f, Shift = %f\n", eye_dist, z_near, z_far, width, x_shift);
-
-		// - calculate our near plane size (horizontal only, right_near is mirrored)
-		float left_near = -eye_dist - ((width - x_shift) * 0.5);
-
-		// - calculate our far plane size (horizontal only, right_far is mirrored)
-		float left_far = -eye_dist - (z_far * (width - x_shift) * 0.5 / z_near);
-		float left_far_right_eye = eye_dist - (z_far * (width + x_shift) * 0.5 / z_near);
-		if (left_far > left_far_right_eye) {
-			// on displays smaller then double our iod, the right eye far frustrum can overtake the left eyes.
-			left_far = left_far_right_eye;
-		}
-
-		// - figure out required z-shift
-		float slope = (left_far - left_near) / (z_far - z_near);
-		float z_shift = (left_near / slope) - z_near;
-
-		// - figure out new vertical near plane size (this will be slightly oversized thanks to our z-shift)
-		float top_near = (height - y_shift) * 0.5;
-		top_near += (top_near / z_near) * z_shift;
-		float bottom_near = -(height + y_shift) * 0.5;
-		bottom_near += (bottom_near / z_near) * z_shift;
-
-		// printf("Left_near = %f, Left_far = %f, Top_near = %f, Bottom_near = %f, Z_shift = %f\n", left_near, left_far, top_near, bottom_near, z_shift);
-
-		// - generate our frustum
-		CameraMatrix combined_matrix;
-		combined_matrix.set_frustum(left_near, -left_near, bottom_near, top_near, z_near + z_shift, z_far + z_shift);
-
-		// and finally move our camera back
-		Transform apply_z_shift;
-		apply_z_shift.origin = Vector3(0.0, 0.0, z_shift); // z negative is forward so this moves it backwards
-		mono_transform *= apply_z_shift;
-
-		// now prepare our scene with our adjusted transform projection matrix
-		_prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
-	} else if (p_eye == XRInterface::EYE_MONO) {
-		// For mono render, prepare as per usual
-		_prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
-	}
-
-	// And render our scene...
-	_render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
-};
-
-void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
-	// Note, in stereo rendering:
-	// - p_cam_transform will be a transform in the middle of our two eyes
-	// - p_cam_projection is a wider frustrum that encompasses both eyes
-
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-
-	render_pass++;
-	uint32_t camera_layer_mask = p_visible_layers;
-
-	RSG::scene_render->set_scene_pass(render_pass);
-
-	if (p_render_buffers.is_valid()) {
-		RSG::scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not)
-	}
-
-	RENDER_TIMESTAMP("Frustum Culling");
-
-	//rasterizer->set_camera(camera->transform, camera_matrix,ortho);
-
-	Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
-
-	Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized());
-	float z_far = p_cam_projection.get_z_far();
-
-	/* STEP 2 - CULL */
-	instance_cull_count = scenario->octree.cull_convex(planes, instance_cull_result, MAX_INSTANCE_CULL);
-	light_cull_count = 0;
-
-	reflection_probe_cull_count = 0;
-	decal_cull_count = 0;
-	gi_probe_cull_count = 0;
-	lightmap_cull_count = 0;
-
-	//light_samplers_culled=0;
-
-	/*
-	print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0));
-	print_line("OTO: "+itos(p_scenario->octree.get_octant_count()));
-	print_line("OTE: "+itos(p_scenario->octree.get_elem_count()));
-	print_line("OTP: "+itos(p_scenario->octree.get_pair_count()));
-	*/
-
-	/* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */
-	//removed, will replace with culling
-
-	/* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */
-	uint64_t frame_number = RSG::rasterizer->get_frame_number();
-	float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
-
-	for (int i = 0; i < instance_cull_count; i++) {
-		Instance *ins = instance_cull_result[i];
-
-		bool keep = false;
-
-		if ((camera_layer_mask & ins->layer_mask) == 0) {
-			//failure
-		} else if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
-			if (light_cull_count < MAX_LIGHTS_CULLED) {
-				InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
-
-				if (!light->geometries.empty()) {
-					//do not add this light if no geometry is affected by it..
-					light_cull_result[light_cull_count] = ins;
-					light_instance_cull_result[light_cull_count] = light->instance;
-					if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(ins->base)) {
-						RSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later
-					}
-
-					light_cull_count++;
-				}
-			}
-		} else if (ins->base_type == RS::INSTANCE_REFLECTION_PROBE && ins->visible) {
-			if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) {
-				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data);
-
-				if (p_reflection_probe != reflection_probe->instance) {
-					//avoid entering The Matrix
-
-					if (!reflection_probe->geometries.empty()) {
-						//do not add this light if no geometry is affected by it..
-
-						if (reflection_probe->reflection_dirty || RSG::scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) {
-							if (!reflection_probe->update_list.in_list()) {
-								reflection_probe->render_step = 0;
-								reflection_probe_render_list.add_last(&reflection_probe->update_list);
-							}
-
-							reflection_probe->reflection_dirty = false;
-						}
-
-						if (RSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
-							reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
-							reflection_probe_cull_count++;
-						}
-					}
-				}
-			}
-		} else if (ins->base_type == RS::INSTANCE_DECAL && ins->visible) {
-			if (decal_cull_count < MAX_DECALS_CULLED) {
-				InstanceDecalData *decal = static_cast<InstanceDecalData *>(ins->base_data);
-
-				if (!decal->geometries.empty()) {
-					//do not add this decal if no geometry is affected by it..
-					decal_instance_cull_result[decal_cull_count] = decal->instance;
-					decal_cull_count++;
-				}
-			}
-
-		} else if (ins->base_type == RS::INSTANCE_GI_PROBE && ins->visible) {
-			InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(ins->base_data);
-			if (!gi_probe->update_element.in_list()) {
-				gi_probe_update_list.add(&gi_probe->update_element);
-			}
-
-			if (gi_probe_cull_count < MAX_GI_PROBES_CULLED) {
-				gi_probe_instance_cull_result[gi_probe_cull_count] = gi_probe->probe_instance;
-				gi_probe_cull_count++;
-			}
-		} else if (ins->base_type == RS::INSTANCE_LIGHTMAP && ins->visible) {
-			if (lightmap_cull_count < MAX_LIGHTMAPS_CULLED) {
-				lightmap_cull_result[lightmap_cull_count] = ins;
-				lightmap_cull_count++;
-			}
-
-		} else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
-			keep = true;
-
-			InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data);
-
-			if (ins->redraw_if_visible) {
-				RenderingServerRaster::redraw_request();
-			}
-
-			if (ins->base_type == RS::INSTANCE_PARTICLES) {
-				//particles visible? process them
-				if (RSG::storage->particles_is_inactive(ins->base)) {
-					//but if nothing is going on, don't do it.
-					keep = false;
-				} else {
-					RSG::storage->particles_request_process(ins->base);
-					RSG::storage->particles_set_view_axis(ins->base, -p_cam_transform.basis.get_axis(2).normalized());
-					//particles visible? request redraw
-					RenderingServerRaster::redraw_request();
-				}
-			}
-
-			if (geom->lighting_dirty) {
-				int l = 0;
-				//only called when lights AABB enter/exit this geometry
-				ins->light_instances.resize(geom->lighting.size());
-
-				for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
-					InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
-
-					ins->light_instances.write[l++] = light->instance;
-				}
-
-				geom->lighting_dirty = false;
-			}
-
-			if (geom->reflection_dirty) {
-				int l = 0;
-				//only called when reflection probe AABB enter/exit this geometry
-				ins->reflection_probe_instances.resize(geom->reflection_probes.size());
-
-				for (List<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
-					InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
-
-					ins->reflection_probe_instances.write[l++] = reflection_probe->instance;
-				}
-
-				geom->reflection_dirty = false;
-			}
-
-			if (geom->gi_probes_dirty) {
-				int l = 0;
-				//only called when reflection probe AABB enter/exit this geometry
-				ins->gi_probe_instances.resize(geom->gi_probes.size());
-
-				for (List<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
-					InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
-
-					ins->gi_probe_instances.write[l++] = gi_probe->probe_instance;
-				}
-
-				geom->gi_probes_dirty = false;
-			}
-
-			if (ins->last_frame_pass != frame_number && !ins->lightmap_target_sh.empty() && !ins->lightmap_sh.empty()) {
-				Color *sh = ins->lightmap_sh.ptrw();
-				const Color *target_sh = ins->lightmap_target_sh.ptr();
-				for (uint32_t j = 0; j < 9; j++) {
-					sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
-				}
-			}
-
-			ins->depth = near_plane.distance_to(ins->transform.origin);
-			ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15);
-		}
-
-		if (!keep) {
-			// remove, no reason to keep
-			instance_cull_count--;
-			SWAP(instance_cull_result[i], instance_cull_result[instance_cull_count]);
-			i--;
-			ins->last_render_pass = 0; // make invalid
-		} else {
-			ins->last_render_pass = render_pass;
-		}
-		ins->last_frame_pass = frame_number;
-	}
-
-	/* STEP 5 - PROCESS LIGHTS */
-
-	RID *directional_light_ptr = &light_instance_cull_result[light_cull_count];
-	directional_light_count = 0;
-
-	// directional lights
-	{
-		Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size());
-		int directional_shadow_count = 0;
-
-		for (List<Instance *>::Element *E = scenario->directional_lights.front(); E; E = E->next()) {
-			if (light_cull_count + directional_light_count >= MAX_LIGHTS_CULLED) {
-				break;
-			}
-
-			if (!E->get()->visible) {
-				continue;
-			}
-
-			InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
-
-			//check shadow..
-
-			if (light) {
-				if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base) && !(RSG::storage->light_get_type(E->get()->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->get()->base))) {
-					lights_with_shadow[directional_shadow_count++] = E->get();
-				}
-				//add to list
-				directional_light_ptr[directional_light_count++] = light->instance;
-			}
-		}
-
-		RSG::scene_render->set_directional_shadow_count(directional_shadow_count);
-
-		for (int i = 0; i < directional_shadow_count; i++) {
-			RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i));
-
-			_light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
-
-			RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i));
-		}
-	}
-
-	if (p_using_shadows) { //setup shadow maps
-
-		//SortArray<Instance*,_InstanceLightsort> sorter;
-		//sorter.sort(light_cull_result,light_cull_count);
-		for (int i = 0; i < light_cull_count; i++) {
-			Instance *ins = light_cull_result[i];
-
-			if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
-				continue;
-			}
-
-			InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
-
-			float coverage = 0.f;
-
-			{ //compute coverage
-
-				Transform cam_xf = p_cam_transform;
-				float zn = p_cam_projection.get_z_near();
-				Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane
-
-				// near plane half width and height
-				Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents();
-
-				switch (RSG::storage->light_get_type(ins->base)) {
-					case RS::LIGHT_OMNI: {
-						float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
-
-						//get two points parallel to near plane
-						Vector3 points[2] = {
-							ins->transform.origin,
-							ins->transform.origin + cam_xf.basis.get_axis(0) * radius
-						};
-
-						if (!p_cam_orthogonal) {
-							//if using perspetive, map them to near plane
-							for (int j = 0; j < 2; j++) {
-								if (p.distance_to(points[j]) < 0) {
-									points[j].z = -zn; //small hack to keep size constant when hitting the screen
-								}
-
-								p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane
-							}
-						}
-
-						float screen_diameter = points[0].distance_to(points[1]) * 2;
-						coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
-					} break;
-					case RS::LIGHT_SPOT: {
-						float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
-						float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
-
-						float w = radius * Math::sin(Math::deg2rad(angle));
-						float d = radius * Math::cos(Math::deg2rad(angle));
-
-						Vector3 base = ins->transform.origin - ins->transform.basis.get_axis(2).normalized() * d;
-
-						Vector3 points[2] = {
-							base,
-							base + cam_xf.basis.get_axis(0) * w
-						};
-
-						if (!p_cam_orthogonal) {
-							//if using perspetive, map them to near plane
-							for (int j = 0; j < 2; j++) {
-								if (p.distance_to(points[j]) < 0) {
-									points[j].z = -zn; //small hack to keep size constant when hitting the screen
-								}
-
-								p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane
-							}
-						}
-
-						float screen_diameter = points[0].distance_to(points[1]) * 2;
-						coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
-
-					} break;
-					default: {
-						ERR_PRINT("Invalid Light Type");
-					}
-				}
-			}
-
-			if (light->shadow_dirty) {
-				light->last_version++;
-				light->shadow_dirty = false;
-			}
-
-			bool redraw = RSG::scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version);
-
-			if (redraw) {
-				//must redraw!
-				RENDER_TIMESTAMP(">Rendering Light " + itos(i));
-				light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
-				RENDER_TIMESTAMP("<Rendering Light " + itos(i));
-			}
-		}
-	}
-
-	/* UPDATE SDFGI */
-
-	if (p_render_buffers.is_valid()) {
-		uint32_t cascade_index[8];
-		uint32_t cascade_sizes[8];
-		const RID *cascade_ptrs[8];
-		uint32_t cascade_count = 0;
-		uint32_t sdfgi_light_cull_count = 0;
-
-		uint32_t prev_cascade = 0xFFFFFFFF;
-		for (int i = 0; i < RSG::scene_render->sdfgi_get_pending_region_count(p_render_buffers); i++) {
-			AABB region = RSG::scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i);
-			uint32_t region_cascade = RSG::scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i);
-
-			if (region_cascade != prev_cascade) {
-				cascade_sizes[cascade_count] = 0;
-				cascade_index[cascade_count] = region_cascade;
-				cascade_ptrs[cascade_count] = &sdfgi_light_cull_result[sdfgi_light_cull_count];
-				cascade_count++;
-				sdfgi_light_cull_pass++;
-				prev_cascade = region_cascade;
-			}
-			uint32_t sdfgi_cull_count = scenario->octree.cull_aabb(region, instance_shadow_cull_result, MAX_INSTANCE_CULL);
-
-			for (uint32_t j = 0; j < sdfgi_cull_count; j++) {
-				Instance *ins = instance_shadow_cull_result[j];
-
-				bool keep = false;
-
-				if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
-					InstanceLightData *instance_light = (InstanceLightData *)ins->base_data;
-					if (instance_light->bake_mode != RS::LIGHT_BAKE_STATIC || region_cascade > instance_light->max_sdfgi_cascade) {
-						continue;
-					}
-
-					if (sdfgi_light_cull_pass != instance_light->sdfgi_cascade_light_pass && sdfgi_light_cull_count < MAX_LIGHTS_CULLED) {
-						instance_light->sdfgi_cascade_light_pass = sdfgi_light_cull_pass;
-						sdfgi_light_cull_result[sdfgi_light_cull_count++] = instance_light->instance;
-						cascade_sizes[cascade_count - 1]++;
-					}
-				} else if ((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
-					if (ins->baked_light) {
-						keep = true;
-					}
-				}
-
-				if (!keep) {
-					// remove, no reason to keep
-					sdfgi_cull_count--;
-					SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[sdfgi_cull_count]);
-					j--;
-				}
-			}
-
-			RSG::scene_render->render_sdfgi(p_render_buffers, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, sdfgi_cull_count);
-			//have to save updated cascades, then update static lights.
-		}
-
-		if (sdfgi_light_cull_count) {
-			RSG::scene_render->render_sdfgi_static_lights(p_render_buffers, cascade_count, cascade_index, cascade_ptrs, cascade_sizes);
-		}
-
-		RSG::scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_light_ptr, directional_light_count, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size());
-	}
-}
-
-RID RenderingServerScene::_render_get_environment(RID p_camera, RID p_scenario) {
-	Camera *camera = camera_owner.getornull(p_camera);
-	if (camera && RSG::scene_render->is_environment(camera->env)) {
-		return camera->env;
-	}
-
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	if (!scenario) {
-		return RID();
-	}
-	if (RSG::scene_render->is_environment(scenario->environment)) {
-		return scenario->environment;
-	}
-
-	if (RSG::scene_render->is_environment(scenario->fallback_environment)) {
-		return scenario->fallback_environment;
-	}
-
-	return RID();
-}
-
-void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-
-	RID camera_effects;
-	if (p_force_camera_effects.is_valid()) {
-		camera_effects = p_force_camera_effects;
-	} else {
-		camera_effects = scenario->camera_effects;
-	}
-	/* PROCESS GEOMETRY AND DRAW SCENE */
-
-	RENDER_TIMESTAMP("Render Scene ");
-	RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
-}
-
-void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
-#ifndef _3D_DISABLED
-
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-
-	RID environment;
-	if (scenario->environment.is_valid()) {
-		environment = scenario->environment;
-	} else {
-		environment = scenario->fallback_environment;
-	}
-	RENDER_TIMESTAMP("Render Empty Scene ");
-	RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
-#endif
-}
-
-bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, int p_step) {
-	InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
-	Scenario *scenario = p_instance->scenario;
-	ERR_FAIL_COND_V(!scenario, true);
-
-	RenderingServerRaster::redraw_request(); //update, so it updates in editor
-
-	if (p_step == 0) {
-		if (!RSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
-			return true; //all full
-		}
-	}
-
-	if (p_step >= 0 && p_step < 6) {
-		static const Vector3 view_normals[6] = {
-			Vector3(+1, 0, 0),
-			Vector3(-1, 0, 0),
-			Vector3(0, +1, 0),
-			Vector3(0, -1, 0),
-			Vector3(0, 0, +1),
-			Vector3(0, 0, -1)
-		};
-		static const Vector3 view_up[6] = {
-			Vector3(0, -1, 0),
-			Vector3(0, -1, 0),
-			Vector3(0, 0, +1),
-			Vector3(0, 0, -1),
-			Vector3(0, -1, 0),
-			Vector3(0, -1, 0)
-		};
-
-		Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base);
-		Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base);
-		float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
-
-		Vector3 edge = view_normals[p_step] * extents;
-		float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
-
-		max_distance = MAX(max_distance, distance);
-
-		//render cubemap side
-		CameraMatrix cm;
-		cm.set_perspective(90, 1, 0.01, max_distance);
-
-		Transform local_view;
-		local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]);
-
-		Transform xform = p_instance->transform * local_view;
-
-		RID shadow_atlas;
-
-		bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base);
-		if (use_shadows) {
-			shadow_atlas = scenario->reflection_probe_shadow_atlas;
-		}
-
-		RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
-		_prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
-		_render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
-
-	} else {
-		//do roughness postprocess step until it believes it's done
-		RENDER_TIMESTAMP("Post-Process Reflection Probe, Step " + itos(p_step));
-		return RSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance);
-	}
-
-	return false;
-}
-
-void RenderingServerScene::render_probes() {
-	/* REFLECTION PROBES */
-
-	SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first();
-
-	bool busy = false;
-
-	while (ref_probe) {
-		SelfList<InstanceReflectionProbeData> *next = ref_probe->next();
-		RID base = ref_probe->self()->owner->base;
-
-		switch (RSG::storage->reflection_probe_get_update_mode(base)) {
-			case RS::REFLECTION_PROBE_UPDATE_ONCE: {
-				if (busy) { //already rendering something
-					break;
-				}
-
-				bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step);
-				if (done) {
-					reflection_probe_render_list.remove(ref_probe);
-				} else {
-					ref_probe->self()->render_step++;
-				}
-
-				busy = true; //do not render another one of this kind
-			} break;
-			case RS::REFLECTION_PROBE_UPDATE_ALWAYS: {
-				int step = 0;
-				bool done = false;
-				while (!done) {
-					done = _render_reflection_probe_step(ref_probe->self()->owner, step);
-					step++;
-				}
-
-				reflection_probe_render_list.remove(ref_probe);
-			} break;
-		}
-
-		ref_probe = next;
-	}
-
-	/* GI PROBES */
-
-	SelfList<InstanceGIProbeData> *gi_probe = gi_probe_update_list.first();
-
-	if (gi_probe) {
-		RENDER_TIMESTAMP("Render GI Probes");
-	}
-
-	while (gi_probe) {
-		SelfList<InstanceGIProbeData> *next = gi_probe->next();
-
-		InstanceGIProbeData *probe = gi_probe->self();
-		//Instance *instance_probe = probe->owner;
-
-		//check if probe must be setup, but don't do if on the lighting thread
-
-		bool cache_dirty = false;
-		int cache_count = 0;
-		{
-			int light_cache_size = probe->light_cache.size();
-			const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr();
-			const RID *instance_caches = probe->light_instances.ptr();
-
-			int idx = 0; //must count visible lights
-			for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) {
-				Instance *instance = E->get();
-				InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
-				if (!instance->visible) {
-					continue;
-				}
-				if (cache_dirty) {
-					//do nothing, since idx must count all visible lights anyway
-				} else if (idx >= light_cache_size) {
-					cache_dirty = true;
-				} else {
-					const InstanceGIProbeData::LightCache *cache = &caches[idx];
-
-					if (
-							instance_caches[idx] != instance_light->instance ||
-							cache->has_shadow != RSG::storage->light_has_shadow(instance->base) ||
-							cache->type != RSG::storage->light_get_type(instance->base) ||
-							cache->transform != instance->transform ||
-							cache->color != RSG::storage->light_get_color(instance->base) ||
-							cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
-							cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
-							cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
-							cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
-							cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
-							cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {
-						cache_dirty = true;
-					}
-				}
-
-				idx++;
-			}
-
-			for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) {
-				Instance *instance = E->get();
-				InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
-				if (!instance->visible) {
-					continue;
-				}
-				if (cache_dirty) {
-					//do nothing, since idx must count all visible lights anyway
-				} else if (idx >= light_cache_size) {
-					cache_dirty = true;
-				} else {
-					const InstanceGIProbeData::LightCache *cache = &caches[idx];
-
-					if (
-							instance_caches[idx] != instance_light->instance ||
-							cache->has_shadow != RSG::storage->light_has_shadow(instance->base) ||
-							cache->type != RSG::storage->light_get_type(instance->base) ||
-							cache->transform != instance->transform ||
-							cache->color != RSG::storage->light_get_color(instance->base) ||
-							cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
-							cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
-							cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
-							cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
-							cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
-							cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||
-							cache->sky_only != RSG::storage->light_directional_is_sky_only(instance->base)) {
-						cache_dirty = true;
-					}
-				}
-
-				idx++;
-			}
-
-			if (idx != light_cache_size) {
-				cache_dirty = true;
-			}
-
-			cache_count = idx;
-		}
-
-		bool update_lights = RSG::scene_render->gi_probe_needs_update(probe->probe_instance);
-
-		if (cache_dirty) {
-			probe->light_cache.resize(cache_count);
-			probe->light_instances.resize(cache_count);
-
-			if (cache_count) {
-				InstanceGIProbeData::LightCache *caches = probe->light_cache.ptrw();
-				RID *instance_caches = probe->light_instances.ptrw();
-
-				int idx = 0; //must count visible lights
-				for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) {
-					Instance *instance = E->get();
-					InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
-					if (!instance->visible) {
-						continue;
-					}
-
-					InstanceGIProbeData::LightCache *cache = &caches[idx];
-
-					instance_caches[idx] = instance_light->instance;
-					cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
-					cache->type = RSG::storage->light_get_type(instance->base);
-					cache->transform = instance->transform;
-					cache->color = RSG::storage->light_get_color(instance->base);
-					cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
-					cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
-					cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
-					cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
-					cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
-					cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
-
-					idx++;
-				}
-				for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) {
-					Instance *instance = E->get();
-					InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
-					if (!instance->visible) {
-						continue;
-					}
-
-					InstanceGIProbeData::LightCache *cache = &caches[idx];
-
-					instance_caches[idx] = instance_light->instance;
-					cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
-					cache->type = RSG::storage->light_get_type(instance->base);
-					cache->transform = instance->transform;
-					cache->color = RSG::storage->light_get_color(instance->base);
-					cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
-					cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
-					cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
-					cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
-					cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
-					cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
-					cache->sky_only = RSG::storage->light_directional_is_sky_only(instance->base);
-
-					idx++;
-				}
-			}
-
-			update_lights = true;
-		}
-
-		instance_cull_count = 0;
-		for (List<InstanceGIProbeData::PairInfo>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) {
-			if (instance_cull_count < MAX_INSTANCE_CULL) {
-				Instance *ins = E->get().geometry;
-				if (!ins->visible) {
-					continue;
-				}
-				InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;
-
-				if (geom->gi_probes_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());
-
-					for (List<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
-						InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
-
-						ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance;
-					}
-
-					geom->gi_probes_dirty = false;
-				}
-
-				instance_cull_result[instance_cull_count++] = E->get().geometry;
-			}
-		}
-
-		RSG::scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, instance_cull_count, (RasterizerScene::InstanceBase **)instance_cull_result);
-
-		gi_probe_update_list.remove(gi_probe);
-
-		gi_probe = next;
-	}
-}
-
-void RenderingServerScene::render_particle_colliders() {
-	while (heightfield_particle_colliders_update_list.front()) {
-		Instance *hfpc = heightfield_particle_colliders_update_list.front()->get();
-
-		if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
-			//update heightfield
-			int cull_count = hfpc->scenario->octree.cull_aabb(hfpc->transformed_aabb, instance_cull_result, MAX_INSTANCE_CULL); //@TODO: cull mask missing
-			for (int i = 0; i < cull_count; i++) {
-				Instance *instance = instance_cull_result[i];
-				if (!instance->visible || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision
-					cull_count--;
-					SWAP(instance_cull_result[i], instance_cull_result[cull_count]);
-				}
-			}
-
-			RSG::scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, (RasterizerScene::InstanceBase **)instance_cull_result, cull_count);
-		}
-		heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front());
-	}
-}
-
-void RenderingServerScene::_update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material) {
-	List<RasterizerStorage::InstanceShaderParam> plist;
-	RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
-	for (List<RasterizerStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) {
-		StringName name = E->get().info.name;
-		if (isparams.has(name)) {
-			if (isparams[name].info.type != E->get().info.type) {
-				WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different data types. Only the first one (in order) will display correctly.");
-			}
-			if (isparams[name].index != E->get().index) {
-				WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different indices. Only the first one (in order) will display correctly.");
-			}
-			continue; //first one found always has priority
-		}
-
-		RasterizerScene::InstanceBase::InstanceShaderParameter isp;
-		isp.index = E->get().index;
-		isp.info = E->get().info;
-		isp.default_value = E->get().default_value;
-		if (existing_isparams.has(name)) {
-			isp.value = existing_isparams[name].value;
-		} else {
-			isp.value = E->get().default_value;
-		}
-		isparams[name] = isp;
-	}
-}
-
-void RenderingServerScene::_update_dirty_instance(Instance *p_instance) {
-	if (p_instance->update_aabb) {
-		_update_instance_aabb(p_instance);
-	}
-
-	if (p_instance->update_dependencies) {
-		p_instance->instance_increase_version();
-
-		if (p_instance->base.is_valid()) {
-			RSG::storage->base_update_dependency(p_instance->base, p_instance);
-		}
-
-		if (p_instance->material_override.is_valid()) {
-			RSG::storage->material_update_dependency(p_instance->material_override, p_instance);
-		}
-
-		if (p_instance->base_type == RS::INSTANCE_MESH) {
-			//remove materials no longer used and un-own them
-
-			int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base);
-			p_instance->materials.resize(new_mat_count);
-
-			int new_blend_shape_count = RSG::storage->mesh_get_blend_shape_count(p_instance->base);
-			if (new_blend_shape_count != p_instance->blend_values.size()) {
-				p_instance->blend_values.resize(new_blend_shape_count);
-				for (int i = 0; i < new_blend_shape_count; i++) {
-					p_instance->blend_values.write[i] = 0;
-				}
-			}
-		}
-
-		if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
-			InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
-
-			bool can_cast_shadows = true;
-			bool is_animated = false;
-			Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> isparams;
-
-			if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
-				can_cast_shadows = false;
-			}
-
-			if (p_instance->material_override.is_valid()) {
-				if (!RSG::storage->material_casts_shadows(p_instance->material_override)) {
-					can_cast_shadows = false;
-				}
-				is_animated = RSG::storage->material_is_animated(p_instance->material_override);
-				_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override);
-			} else {
-				if (p_instance->base_type == RS::INSTANCE_MESH) {
-					RID mesh = p_instance->base;
-
-					if (mesh.is_valid()) {
-						bool cast_shadows = false;
-
-						for (int i = 0; i < p_instance->materials.size(); i++) {
-							RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i);
-
-							if (!mat.is_valid()) {
-								cast_shadows = true;
-							} else {
-								if (RSG::storage->material_casts_shadows(mat)) {
-									cast_shadows = true;
-								}
-
-								if (RSG::storage->material_is_animated(mat)) {
-									is_animated = true;
-								}
-
-								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
-
-								RSG::storage->material_update_dependency(mat, p_instance);
-							}
-						}
-
-						if (!cast_shadows) {
-							can_cast_shadows = false;
-						}
-					}
-
-				} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {
-					RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base);
-					if (mesh.is_valid()) {
-						bool cast_shadows = false;
-
-						int sc = RSG::storage->mesh_get_surface_count(mesh);
-						for (int i = 0; i < sc; i++) {
-							RID mat = RSG::storage->mesh_surface_get_material(mesh, i);
-
-							if (!mat.is_valid()) {
-								cast_shadows = true;
-
-							} else {
-								if (RSG::storage->material_casts_shadows(mat)) {
-									cast_shadows = true;
-								}
-								if (RSG::storage->material_is_animated(mat)) {
-									is_animated = true;
-								}
-
-								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
-
-								RSG::storage->material_update_dependency(mat, p_instance);
-							}
-						}
-
-						if (!cast_shadows) {
-							can_cast_shadows = false;
-						}
-
-						RSG::storage->base_update_dependency(mesh, p_instance);
-					}
-				} else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) {
-					RID mat = RSG::storage->immediate_get_material(p_instance->base);
-
-					if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) {
-						can_cast_shadows = false;
-					}
-
-					if (mat.is_valid() && RSG::storage->material_is_animated(mat)) {
-						is_animated = true;
-					}
-
-					if (mat.is_valid()) {
-						_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
-					}
-
-					if (mat.is_valid()) {
-						RSG::storage->material_update_dependency(mat, p_instance);
-					}
-
-				} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
-					bool cast_shadows = false;
-
-					int dp = RSG::storage->particles_get_draw_passes(p_instance->base);
-
-					for (int i = 0; i < dp; i++) {
-						RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i);
-						if (!mesh.is_valid()) {
-							continue;
-						}
-
-						int sc = RSG::storage->mesh_get_surface_count(mesh);
-						for (int j = 0; j < sc; j++) {
-							RID mat = RSG::storage->mesh_surface_get_material(mesh, j);
-
-							if (!mat.is_valid()) {
-								cast_shadows = true;
-							} else {
-								if (RSG::storage->material_casts_shadows(mat)) {
-									cast_shadows = true;
-								}
-
-								if (RSG::storage->material_is_animated(mat)) {
-									is_animated = true;
-								}
-
-								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
-
-								RSG::storage->material_update_dependency(mat, p_instance);
-							}
-						}
-					}
-
-					if (!cast_shadows) {
-						can_cast_shadows = false;
-					}
-				}
-			}
-
-			if (can_cast_shadows != geom->can_cast_shadows) {
-				//ability to cast shadows change, let lights now
-				for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
-					InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
-					light->shadow_dirty = true;
-				}
-
-				geom->can_cast_shadows = can_cast_shadows;
-			}
-
-			geom->material_is_animated = is_animated;
-			p_instance->instance_shader_parameters = isparams;
-
-			if (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) {
-					p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
-					for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
-						if (E->get().value.get_type() != Variant::NIL) {
-							RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value);
-						}
-					}
-				} else {
-					RSG::storage->global_variables_instance_free(p_instance->self);
-					p_instance->instance_allocated_shader_parameters_offset = -1;
-				}
-			}
-		}
-
-		if (p_instance->skeleton.is_valid()) {
-			RSG::storage->skeleton_update_dependency(p_instance->skeleton, p_instance);
-		}
-
-		p_instance->clean_up_dependencies();
-	}
-
-	_instance_update_list.remove(&p_instance->update_item);
-
-	_update_instance(p_instance);
-
-	p_instance->update_aabb = false;
-	p_instance->update_dependencies = false;
-}
-
-void RenderingServerScene::update_dirty_instances() {
-	RSG::storage->update_dirty_resources();
-
-	while (_instance_update_list.first()) {
-		_update_dirty_instance(_instance_update_list.first()->self());
-	}
-}
-
-bool RenderingServerScene::free(RID p_rid) {
-	if (camera_owner.owns(p_rid)) {
-		Camera *camera = camera_owner.getornull(p_rid);
-
-		camera_owner.free(p_rid);
-		memdelete(camera);
-
-	} else if (scenario_owner.owns(p_rid)) {
-		Scenario *scenario = scenario_owner.getornull(p_rid);
-
-		while (scenario->instances.first()) {
-			instance_set_scenario(scenario->instances.first()->self()->self, RID());
-		}
-		RSG::scene_render->free(scenario->reflection_probe_shadow_atlas);
-		RSG::scene_render->free(scenario->reflection_atlas);
-		scenario_owner.free(p_rid);
-		memdelete(scenario);
-
-	} else if (instance_owner.owns(p_rid)) {
-		// delete the instance
-
-		update_dirty_instances();
-
-		Instance *instance = instance_owner.getornull(p_rid);
-
-		instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0);
-		instance_set_scenario(p_rid, RID());
-		instance_set_base(p_rid, RID());
-		instance_geometry_set_material_override(p_rid, RID());
-		instance_attach_skeleton(p_rid, RID());
-
-		if (instance->instance_allocated_shader_parameters) {
-			//free the used shader parameters
-			RSG::storage->global_variables_instance_free(instance->self);
-		}
-		update_dirty_instances(); //in case something changed this
-
-		instance_owner.free(p_rid);
-		memdelete(instance);
-	} else {
-		return false;
-	}
-
-	return true;
-}
-
-TypedArray<Image> RenderingServerScene::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) {
-	return RSG::scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);
-}
-
-RenderingServerScene *RenderingServerScene::singleton = nullptr;
-
 RenderingServerScene::RenderingServerScene() {
-	render_pass = 1;
-	singleton = this;
 }
 
 RenderingServerScene::~RenderingServerScene() {

+ 140 - 415
servers/rendering/rendering_server_scene.h

@@ -28,450 +28,175 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef VISUALSERVERSCENE_H
-#define VISUALSERVERSCENE_H
+#ifndef RENDERINGSERVERSCENE_H
+#define RENDERINGSERVERSCENE_H
 
 #include "servers/rendering/rasterizer.h"
-
-#include "core/math/geometry_3d.h"
-#include "core/math/octree.h"
-#include "core/os/semaphore.h"
-#include "core/os/thread.h"
-#include "core/templates/local_vector.h"
-#include "core/templates/rid_owner.h"
-#include "core/templates/self_list.h"
 #include "servers/xr/xr_interface.h"
 
 class RenderingServerScene {
 public:
-	enum {
-		MAX_INSTANCE_CULL = 65536,
-		MAX_LIGHTS_CULLED = 4096,
-		MAX_REFLECTION_PROBES_CULLED = 4096,
-		MAX_DECALS_CULLED = 4096,
-		MAX_GI_PROBES_CULLED = 4096,
-		MAX_ROOM_CULL = 32,
-		MAX_LIGHTMAPS_CULLED = 4096,
-		MAX_EXTERIOR_PORTALS = 128,
-	};
-
-	uint64_t render_pass;
-
-	static RenderingServerScene *singleton;
-
-	/* CAMERA API */
-
-	struct Camera {
-		enum Type {
-			PERSPECTIVE,
-			ORTHOGONAL,
-			FRUSTUM
-		};
-		Type type;
-		float fov;
-		float znear, zfar;
-		float size;
-		Vector2 offset;
-		uint32_t visible_layers;
-		bool vaspect;
-		RID env;
-		RID effects;
-
-		Transform transform;
-
-		Camera() {
-			visible_layers = 0xFFFFFFFF;
-			fov = 75;
-			type = PERSPECTIVE;
-			znear = 0.05;
-			zfar = 100;
-			size = 1.0;
-			offset = Vector2();
-			vaspect = false;
-		}
-	};
-
-	mutable RID_PtrOwner<Camera> camera_owner;
-
-	virtual RID camera_create();
-	virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
-	virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
-	virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
-	virtual void camera_set_transform(RID p_camera, const Transform &p_transform);
-	virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers);
-	virtual void camera_set_environment(RID p_camera, RID p_env);
-	virtual void camera_set_camera_effects(RID p_camera, RID p_fx);
-	virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable);
-
-	/* SCENARIO API */
-
-	struct Instance;
-
-	struct Scenario {
-		RS::ScenarioDebugMode debug;
-		RID self;
-
-		Octree<Instance, true> octree;
-
-		List<Instance *> directional_lights;
-		RID environment;
-		RID fallback_environment;
-		RID camera_effects;
-		RID reflection_probe_shadow_atlas;
-		RID reflection_atlas;
-
-		SelfList<Instance>::List instances;
-
-		LocalVector<RID> dynamic_lights;
-
-		Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; }
-	};
-
-	mutable RID_PtrOwner<Scenario> scenario_owner;
-
-	static void *_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int);
-	static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *);
-
-	virtual RID scenario_create();
-
-	virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
-	virtual void scenario_set_environment(RID p_scenario, RID p_environment);
-	virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx);
-	virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
-	virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count);
-
-	/* INSTANCING API */
-
-	struct InstanceBaseData {
-		virtual ~InstanceBaseData() {}
-	};
-
-	struct Instance : RasterizerScene::InstanceBase {
-		RID self;
-		//scenario stuff
-		OctreeElementID octree_id;
-		Scenario *scenario;
-		SelfList<Instance> scenario_item;
-
-		//aabb stuff
-		bool update_aabb;
-		bool update_dependencies;
-
-		SelfList<Instance> update_item;
-
-		AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better?
-		float extra_margin;
-		ObjectID object_id;
-
-		float lod_begin;
-		float lod_end;
-		float lod_begin_hysteresis;
-		float lod_end_hysteresis;
-		RID lod_instance;
-
-		Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior
-
-		uint64_t last_render_pass;
-		uint64_t last_frame_pass;
-
-		uint64_t version; // changes to this, and changes to base increase version
-
-		InstanceBaseData *base_data;
-
-		virtual void dependency_deleted(RID p_dependency) {
-			if (p_dependency == base) {
-				singleton->instance_set_base(self, RID());
-			} else if (p_dependency == skeleton) {
-				singleton->instance_attach_skeleton(self, RID());
-			} else {
-				singleton->_instance_queue_update(this, false, true);
-			}
-		}
-
-		virtual void dependency_changed(bool p_aabb, bool p_dependencies) {
-			singleton->_instance_queue_update(this, p_aabb, p_dependencies);
-		}
-
-		Instance() :
-				scenario_item(this),
-				update_item(this) {
-			octree_id = 0;
-			scenario = nullptr;
+	virtual RID camera_create() = 0;
+
+	virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
+	virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
+	virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0;
+	virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0;
+	virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
+	virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
+	virtual void camera_set_camera_effects(RID p_camera, RID p_fx) = 0;
+	virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0;
+	virtual bool is_camera(RID p_camera) const = 0;
+
+	virtual RID scenario_create() = 0;
+
+	virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) = 0;
+	virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
+	virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx) = 0;
+	virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
+	virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) = 0;
+	virtual bool is_scenario(RID p_scenario) const = 0;
+	virtual RID scenario_get_environment(RID p_scenario) = 0;
+
+	virtual RID instance_create() = 0;
+
+	virtual void instance_set_base(RID p_instance, RID p_base) = 0;
+	virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0;
+	virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0;
+	virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
+	virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0;
+	virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0;
+	virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0;
+	virtual void instance_set_visible(RID p_instance, bool p_visible) = 0;
+
+	virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb) = 0;
+
+	virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0;
+	virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0;
+
+	virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
 
-			update_aabb = false;
-			update_dependencies = false;
+	// don't use these in a game!
+	virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0;
+	virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0;
+	virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0;
 
-			extra_margin = 0;
+	virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) = 0;
+	virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) = 0;
+	virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
 
-			visible = true;
+	virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
+	virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
+	virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0;
 
-			lod_begin = 0;
-			lod_end = 0;
-			lod_begin_hysteresis = 0;
-			lod_end_hysteresis = 0;
+	virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0;
+	virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0;
+	virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0;
+	virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0;
 
-			last_render_pass = 0;
-			last_frame_pass = 0;
-			version = 1;
-			base_data = nullptr;
+	virtual void directional_shadow_atlas_set_size(int p_size) = 0;
 
-			custom_aabb = nullptr;
-		}
+	/* SKY API */
 
-		~Instance() {
-			if (base_data) {
-				memdelete(base_data);
-			}
-			if (custom_aabb) {
-				memdelete(custom_aabb);
-			}
-		}
-	};
-
-	SelfList<Instance>::List _instance_update_list;
-	void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
-
-	struct InstanceGeometryData : public InstanceBaseData {
-		List<Instance *> lighting;
-		bool lighting_dirty;
-		bool can_cast_shadows;
-		bool material_is_animated;
-
-		List<Instance *> decals;
-		bool decal_dirty;
+	virtual RID sky_create() = 0;
+	virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0;
+	virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0;
+	virtual void sky_set_material(RID p_sky, RID p_material) = 0;
+	virtual Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0;
 
-		List<Instance *> reflection_probes;
-		bool reflection_dirty;
-
-		List<Instance *> gi_probes;
-		bool gi_probes_dirty;
-
-		List<Instance *> lightmap_captures;
-
-		InstanceGeometryData() {
-			lighting_dirty = false;
-			reflection_dirty = true;
-			can_cast_shadows = true;
-			material_is_animated = true;
-			gi_probes_dirty = true;
-			decal_dirty = true;
-		}
-	};
-
-	struct InstanceReflectionProbeData : public InstanceBaseData {
-		Instance *owner;
-
-		struct PairInfo {
-			List<Instance *>::Element *L; //reflection iterator in geometry
-			Instance *geometry;
-		};
-		List<PairInfo> geometries;
-
-		RID instance;
-		bool reflection_dirty;
-		SelfList<InstanceReflectionProbeData> update_list;
-
-		int render_step;
-
-		InstanceReflectionProbeData() :
-				update_list(this) {
-			reflection_dirty = true;
-			render_step = -1;
-		}
-	};
-
-	struct InstanceDecalData : public InstanceBaseData {
-		Instance *owner;
-		RID instance;
-
-		struct PairInfo {
-			List<Instance *>::Element *L; //reflection iterator in geometry
-			Instance *geometry;
-		};
-		List<PairInfo> geometries;
-
-		InstanceDecalData() {
-		}
-	};
-
-	SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
-
-	struct InstanceLightData : public InstanceBaseData {
-		struct PairInfo {
-			List<Instance *>::Element *L; //light iterator in geometry
-			Instance *geometry;
-		};
-
-		RID instance;
-		uint64_t last_version;
-		List<Instance *>::Element *D; // directional light in scenario
-
-		bool shadow_dirty;
-
-		List<PairInfo> geometries;
-
-		Instance *baked_light;
-
-		RS::LightBakeMode bake_mode;
-		uint32_t max_sdfgi_cascade = 2;
-
-		uint64_t sdfgi_cascade_light_pass = 0;
-
-		InstanceLightData() {
-			bake_mode = RS::LIGHT_BAKE_DISABLED;
-			shadow_dirty = true;
-			D = nullptr;
-			last_version = 0;
-			baked_light = nullptr;
-		}
-	};
-
-	struct InstanceGIProbeData : public InstanceBaseData {
-		Instance *owner;
-
-		struct PairInfo {
-			List<Instance *>::Element *L; //gi probe iterator in geometry
-			Instance *geometry;
-		};
-
-		List<PairInfo> geometries;
-		List<PairInfo> dynamic_geometries;
-
-		Set<Instance *> lights;
-
-		struct LightCache {
-			RS::LightType type;
-			Transform transform;
-			Color color;
-			float energy;
-			float bake_energy;
-			float radius;
-			float attenuation;
-			float spot_angle;
-			float spot_attenuation;
-			bool has_shadow;
-			bool sky_only;
-		};
-
-		Vector<LightCache> light_cache;
-		Vector<RID> light_instances;
-
-		RID probe_instance;
-
-		bool invalid;
-		uint32_t base_version;
-
-		SelfList<InstanceGIProbeData> update_element;
-
-		InstanceGIProbeData() :
-				update_element(this) {
-			invalid = true;
-			base_version = 0;
-		}
-	};
-
-	SelfList<InstanceGIProbeData>::List gi_probe_update_list;
-
-	struct InstanceLightmapData : public InstanceBaseData {
-		struct PairInfo {
-			List<Instance *>::Element *L; //iterator in geometry
-			Instance *geometry;
-		};
-		List<PairInfo> geometries;
-
-		Set<Instance *> users;
-
-		InstanceLightmapData() {
-		}
-	};
-
-	Set<Instance *> heightfield_particle_colliders_update_list;
-
-	int instance_cull_count;
-	Instance *instance_cull_result[MAX_INSTANCE_CULL];
-	Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
-	Instance *light_cull_result[MAX_LIGHTS_CULLED];
-	RID sdfgi_light_cull_result[MAX_LIGHTS_CULLED];
-	RID light_instance_cull_result[MAX_LIGHTS_CULLED];
-	uint64_t sdfgi_light_cull_pass = 0;
-	int light_cull_count;
-	int directional_light_count;
-	RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
-	RID decal_instance_cull_result[MAX_DECALS_CULLED];
-	int reflection_probe_cull_count;
-	int decal_cull_count;
-	RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
-	int gi_probe_cull_count;
-	Instance *lightmap_cull_result[MAX_LIGHTS_CULLED];
-	int lightmap_cull_count;
-
-	RID_PtrOwner<Instance> instance_owner;
-
-	virtual RID instance_create();
-
-	virtual void instance_set_base(RID p_instance, RID p_base);
-	virtual void instance_set_scenario(RID p_instance, RID p_scenario);
-	virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask);
-	virtual void instance_set_transform(RID p_instance, const Transform &p_transform);
-	virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id);
-	virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
-	virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material);
-	virtual void instance_set_visible(RID p_instance, bool p_visible);
-
-	virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
-
-	virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton);
-	virtual void instance_set_exterior(RID p_instance, bool p_enabled);
-
-	virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin);
+	/* ENVIRONMENT API */
 
-	// don't use these in a game!
-	virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const;
-	virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
-	virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const;
+	virtual RID environment_create() = 0;
+
+	virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
+	virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
+	virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
+	virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
+	virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
+	virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
+	virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
+	virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0;
+
+	virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0;
+	virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
+	virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
+
+	virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0;
+
+	virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
+	virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
+	virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) = 0;
+	virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) = 0;
+
+	virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0;
+	virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
+
+	virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0;
+
+	virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) = 0;
+
+	virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+
+	virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
+	virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
+
+	virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
+
+	virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0;
+
+	virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
+
+	virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0;
+
+	virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0;
+	virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
+
+	virtual bool is_environment(RID p_environment) const = 0;
+
+	virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
+	virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0;
+	virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0;
+
+	/* Camera Effects */
+
+	virtual RID camera_effects_create() = 0;
 
-	virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled);
-	virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting);
-	virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
+	virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0;
+	virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0;
 
-	virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
-	virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
-	virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
+	virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
+	virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
 
-	void _update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material);
+	virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
+	virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
 
-	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 Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const;
-	virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const;
+	virtual RID shadow_atlas_create() = 0;
+	virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0;
+	virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
 
-	_FORCE_INLINE_ void _update_instance(Instance *p_instance);
-	_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
-	_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
-	_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
+	/* Render Buffers */
 
-	_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario);
+	virtual RID render_buffers_create() = 0;
+	virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
 
-	RID _render_get_environment(RID p_camera, RID p_scenario);
+	virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
 
-	bool _render_reflection_probe_step(Instance *p_instance, int p_step);
-	void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
-	void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
-	void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
+	virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
+	virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
 
-	void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
-	void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
-	void update_dirty_instances();
+	virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
 
-	void render_particle_colliders();
-	void render_probes();
+	virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
+	virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) = 0;
+	virtual void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) = 0;
 
-	TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size);
+	virtual void update() = 0;
+	virtual void render_probes() = 0;
 
-	bool free(RID p_rid);
+	virtual bool free(RID p_rid) = 0;
 
 	RenderingServerScene();
 	virtual ~RenderingServerScene();
 };
 
-#endif // VISUALSERVERSCENE_H
+#endif // RENDERINGSERVERSCENE_H

+ 3072 - 0
servers/rendering/rendering_server_scene_raster.cpp

@@ -0,0 +1,3072 @@
+/*************************************************************************/
+/*  rendering_server_scene_raster.cpp                                    */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "rendering_server_scene_raster.h"
+
+#include "core/os/os.h"
+#include "rendering_server_default.h"
+#include "rendering_server_globals.h"
+
+#include <new>
+
+/* CAMERA API */
+
+RID RenderingServerSceneRaster::camera_create() {
+	Camera *camera = memnew(Camera);
+	return camera_owner.make_rid(camera);
+}
+
+void RenderingServerSceneRaster::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+	camera->type = Camera::PERSPECTIVE;
+	camera->fov = p_fovy_degrees;
+	camera->znear = p_z_near;
+	camera->zfar = p_z_far;
+}
+
+void RenderingServerSceneRaster::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+	camera->type = Camera::ORTHOGONAL;
+	camera->size = p_size;
+	camera->znear = p_z_near;
+	camera->zfar = p_z_far;
+}
+
+void RenderingServerSceneRaster::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+	camera->type = Camera::FRUSTUM;
+	camera->size = p_size;
+	camera->offset = p_offset;
+	camera->znear = p_z_near;
+	camera->zfar = p_z_far;
+}
+
+void RenderingServerSceneRaster::camera_set_transform(RID p_camera, const Transform &p_transform) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+	camera->transform = p_transform.orthonormalized();
+}
+
+void RenderingServerSceneRaster::camera_set_cull_mask(RID p_camera, uint32_t p_layers) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+
+	camera->visible_layers = p_layers;
+}
+
+void RenderingServerSceneRaster::camera_set_environment(RID p_camera, RID p_env) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+	camera->env = p_env;
+}
+
+void RenderingServerSceneRaster::camera_set_camera_effects(RID p_camera, RID p_fx) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+	camera->effects = p_fx;
+}
+
+void RenderingServerSceneRaster::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+	camera->vaspect = p_enable;
+}
+
+bool RenderingServerSceneRaster::is_camera(RID p_camera) const {
+	return camera_owner.owns(p_camera);
+}
+
+/* SCENARIO API */
+
+void *RenderingServerSceneRaster::_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int) {
+	//RenderingServerSceneRaster *self = (RenderingServerSceneRaster*)p_self;
+	Instance *A = p_A;
+	Instance *B = p_B;
+
+	//instance indices are designed so greater always contains lesser
+	if (A->base_type > B->base_type) {
+		SWAP(A, B); //lesser always first
+	}
+
+	if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		InstanceLightData::PairInfo pinfo;
+		pinfo.geometry = A;
+		pinfo.L = geom->lighting.push_back(B);
+
+		List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo);
+
+		if (geom->can_cast_shadows) {
+			light->shadow_dirty = true;
+		}
+		geom->lighting_dirty = true;
+
+		return E; //this element should make freeing faster
+	} else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		InstanceReflectionProbeData::PairInfo pinfo;
+		pinfo.geometry = A;
+		pinfo.L = geom->reflection_probes.push_back(B);
+
+		List<InstanceReflectionProbeData::PairInfo>::Element *E = reflection_probe->geometries.push_back(pinfo);
+
+		geom->reflection_dirty = true;
+
+		return E; //this element should make freeing faster
+	} else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		InstanceDecalData::PairInfo pinfo;
+		pinfo.geometry = A;
+		pinfo.L = geom->decals.push_back(B);
+
+		List<InstanceDecalData::PairInfo>::Element *E = decal->geometries.push_back(pinfo);
+
+		geom->decal_dirty = true;
+
+		return E; //this element should make freeing faster
+	} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		if (A->dynamic_gi) {
+			InstanceLightmapData::PairInfo pinfo;
+			pinfo.geometry = A;
+			pinfo.L = geom->lightmap_captures.push_back(B);
+			List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.push_back(pinfo);
+			((RenderingServerSceneRaster *)p_self)->_instance_queue_update(A, false, false); //need to update capture
+			return E; //this element should make freeing faster
+		} else {
+			return nullptr;
+		}
+
+	} else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		InstanceGIProbeData::PairInfo pinfo;
+		pinfo.geometry = A;
+		pinfo.L = geom->gi_probes.push_back(B);
+
+		List<InstanceGIProbeData::PairInfo>::Element *E;
+		if (A->dynamic_gi) {
+			E = gi_probe->dynamic_geometries.push_back(pinfo);
+		} else {
+			E = gi_probe->geometries.push_back(pinfo);
+		}
+
+		geom->gi_probes_dirty = true;
+
+		return E; //this element should make freeing faster
+
+	} else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
+		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
+		return gi_probe->lights.insert(A);
+	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
+		RSG::storage->particles_add_collision(A->base, B);
+	}
+
+	return nullptr;
+}
+
+void RenderingServerSceneRaster::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *udata) {
+	//RenderingServerSceneRaster *self = (RenderingServerSceneRaster*)p_self;
+	Instance *A = p_A;
+	Instance *B = p_B;
+
+	//instance indices are designed so greater always contains lesser
+	if (A->base_type > B->base_type) {
+		SWAP(A, B); //lesser always first
+	}
+
+	if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		List<InstanceLightData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightData::PairInfo>::Element *>(udata);
+
+		geom->lighting.erase(E->get().L);
+		light->geometries.erase(E);
+
+		if (geom->can_cast_shadows) {
+			light->shadow_dirty = true;
+		}
+		geom->lighting_dirty = true;
+
+	} else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		List<InstanceReflectionProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceReflectionProbeData::PairInfo>::Element *>(udata);
+
+		geom->reflection_probes.erase(E->get().L);
+		reflection_probe->geometries.erase(E);
+
+		geom->reflection_dirty = true;
+	} else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		List<InstanceDecalData::PairInfo>::Element *E = reinterpret_cast<List<InstanceDecalData::PairInfo>::Element *>(udata);
+
+		geom->decals.erase(E->get().L);
+		decal->geometries.erase(E);
+
+		geom->decal_dirty = true;
+	} else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+		if (udata) { //only for dynamic geometries
+			InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data);
+			InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+			List<InstanceLightmapData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightmapData::PairInfo>::Element *>(udata);
+
+			geom->lightmap_captures.erase(E->get().L);
+			lightmap_data->geometries.erase(E);
+			((RenderingServerSceneRaster *)p_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)) {
+		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
+
+		List<InstanceGIProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceGIProbeData::PairInfo>::Element *>(udata);
+
+		geom->gi_probes.erase(E->get().L);
+		if (A->dynamic_gi) {
+			gi_probe->dynamic_geometries.erase(E);
+		} else {
+			gi_probe->geometries.erase(E);
+		}
+
+		geom->gi_probes_dirty = true;
+
+	} else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) {
+		InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
+		Set<Instance *>::Element *E = reinterpret_cast<Set<Instance *>::Element *>(udata);
+
+		gi_probe->lights.erase(E);
+	} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
+		RSG::storage->particles_remove_collision(A->base, B);
+	}
+}
+
+RID RenderingServerSceneRaster::scenario_create() {
+	Scenario *scenario = memnew(Scenario);
+	ERR_FAIL_COND_V(!scenario, RID());
+	RID scenario_rid = scenario_owner.make_rid(scenario);
+	scenario->self = scenario_rid;
+
+	scenario->octree.set_pair_callback(_instance_pair, this);
+	scenario->octree.set_unpair_callback(_instance_unpair, this);
+	scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create();
+	scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest
+	scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4);
+	scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);
+	scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);
+	scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);
+	scenario->reflection_atlas = scene_render->reflection_atlas_create();
+	return scenario_rid;
+}
+
+void RenderingServerSceneRaster::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) {
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND(!scenario);
+	scenario->debug = p_debug_mode;
+}
+
+void RenderingServerSceneRaster::scenario_set_environment(RID p_scenario, RID p_environment) {
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND(!scenario);
+	scenario->environment = p_environment;
+}
+
+void RenderingServerSceneRaster::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) {
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND(!scenario);
+	scenario->camera_effects = p_camera_effects;
+}
+
+void RenderingServerSceneRaster::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND(!scenario);
+	scenario->fallback_environment = p_environment;
+}
+
+void RenderingServerSceneRaster::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND(!scenario);
+	scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);
+}
+
+bool RenderingServerSceneRaster::is_scenario(RID p_scenario) const {
+	return scenario_owner.owns(p_scenario);
+}
+
+RID RenderingServerSceneRaster::scenario_get_environment(RID p_scenario) {
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND_V(!scenario, RID());
+	return scenario->environment;
+}
+
+/* INSTANCING API */
+
+void RenderingServerSceneRaster::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
+	if (p_update_aabb) {
+		p_instance->update_aabb = true;
+	}
+	if (p_update_dependencies) {
+		p_instance->update_dependencies = true;
+	}
+
+	if (p_instance->update_item.in_list()) {
+		return;
+	}
+
+	_instance_update_list.add(&p_instance->update_item);
+}
+
+RID RenderingServerSceneRaster::instance_create() {
+	Instance *instance = memnew(Instance);
+	ERR_FAIL_COND_V(!instance, RID());
+
+	RID instance_rid = instance_owner.make_rid(instance);
+	instance->self = instance_rid;
+
+	return instance_rid;
+}
+
+void RenderingServerSceneRaster::instance_set_base(RID p_instance, RID p_base) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	Scenario *scenario = instance->scenario;
+
+	if (instance->base_type != RS::INSTANCE_NONE) {
+		//free anything related to that base
+
+		if (scenario && instance->octree_id) {
+			scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
+			instance->octree_id = 0;
+		}
+
+		switch (instance->base_type) {
+			case RS::INSTANCE_LIGHT: {
+				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
+
+				if (scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+					scenario->dynamic_lights.erase(light->instance);
+				}
+
+#ifdef DEBUG_ENABLED
+				if (light->geometries.size()) {
+					ERR_PRINT("BUG, indexing did not unpair geometries from light.");
+				}
+#endif
+				if (scenario && light->D) {
+					scenario->directional_lights.erase(light->D);
+					light->D = nullptr;
+				}
+				scene_render->free(light->instance);
+			} break;
+			case RS::INSTANCE_REFLECTION_PROBE: {
+				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
+				scene_render->free(reflection_probe->instance);
+				if (reflection_probe->update_list.in_list()) {
+					reflection_probe_render_list.remove(&reflection_probe->update_list);
+				}
+			} break;
+			case RS::INSTANCE_DECAL: {
+				InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);
+				scene_render->free(decal->instance);
+
+			} break;
+			case RS::INSTANCE_LIGHTMAP: {
+				InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(instance->base_data);
+				//erase dependencies, since no longer a lightmap
+				while (lightmap_data->users.front()) {
+					instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0);
+				}
+			} break;
+			case RS::INSTANCE_GI_PROBE: {
+				InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
+#ifdef DEBUG_ENABLED
+				if (gi_probe->geometries.size()) {
+					ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe.");
+				}
+#endif
+#ifdef DEBUG_ENABLED
+				if (gi_probe->lights.size()) {
+					ERR_PRINT("BUG, indexing did not unpair lights from GIProbe.");
+				}
+#endif
+				if (gi_probe->update_element.in_list()) {
+					gi_probe_update_list.remove(&gi_probe->update_element);
+				}
+
+				scene_render->free(gi_probe->probe_instance);
+
+			} break;
+			default: {
+			}
+		}
+
+		if (instance->base_data) {
+			memdelete(instance->base_data);
+			instance->base_data = nullptr;
+		}
+
+		instance->blend_values.clear();
+		instance->materials.clear();
+	}
+
+	instance->base_type = RS::INSTANCE_NONE;
+	instance->base = RID();
+
+	if (p_base.is_valid()) {
+		instance->base_type = RSG::storage->get_base_type(p_base);
+		ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE);
+
+		switch (instance->base_type) {
+			case RS::INSTANCE_LIGHT: {
+				InstanceLightData *light = memnew(InstanceLightData);
+
+				if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
+					light->D = scenario->directional_lights.push_back(instance);
+				}
+
+				light->instance = scene_render->light_instance_create(p_base);
+
+				instance->base_data = light;
+			} break;
+			case RS::INSTANCE_MESH:
+			case RS::INSTANCE_MULTIMESH:
+			case RS::INSTANCE_IMMEDIATE:
+			case RS::INSTANCE_PARTICLES: {
+				InstanceGeometryData *geom = memnew(InstanceGeometryData);
+				instance->base_data = geom;
+				if (instance->base_type == RS::INSTANCE_MESH) {
+					instance->blend_values.resize(RSG::storage->mesh_get_blend_shape_count(p_base));
+				}
+			} break;
+			case RS::INSTANCE_REFLECTION_PROBE: {
+				InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
+				reflection_probe->owner = instance;
+				instance->base_data = reflection_probe;
+
+				reflection_probe->instance = scene_render->reflection_probe_instance_create(p_base);
+			} break;
+			case RS::INSTANCE_DECAL: {
+				InstanceDecalData *decal = memnew(InstanceDecalData);
+				decal->owner = instance;
+				instance->base_data = decal;
+
+				decal->instance = scene_render->decal_instance_create(p_base);
+			} break;
+			case RS::INSTANCE_LIGHTMAP: {
+				InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
+				instance->base_data = lightmap_data;
+				//lightmap_data->instance = scene_render->lightmap_data_instance_create(p_base);
+			} break;
+			case RS::INSTANCE_GI_PROBE: {
+				InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData);
+				instance->base_data = gi_probe;
+				gi_probe->owner = instance;
+
+				if (scenario && !gi_probe->update_element.in_list()) {
+					gi_probe_update_list.add(&gi_probe->update_element);
+				}
+
+				gi_probe->probe_instance = scene_render->gi_probe_instance_create(p_base);
+
+			} break;
+			default: {
+			}
+		}
+
+		instance->base = p_base;
+
+		//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
+		RSG::storage->base_update_dependency(p_base, instance);
+	}
+
+	_instance_queue_update(instance, true, true);
+}
+
+void RenderingServerSceneRaster::instance_set_scenario(RID p_instance, RID p_scenario) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	if (instance->scenario) {
+		instance->scenario->instances.remove(&instance->scenario_item);
+
+		if (instance->octree_id) {
+			instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
+			instance->octree_id = 0;
+		}
+
+		switch (instance->base_type) {
+			case RS::INSTANCE_LIGHT: {
+				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
+#ifdef DEBUG_ENABLED
+				if (light->geometries.size()) {
+					ERR_PRINT("BUG, indexing did not unpair geometries from light.");
+				}
+#endif
+				if (light->D) {
+					instance->scenario->directional_lights.erase(light->D);
+					light->D = nullptr;
+				}
+			} break;
+			case RS::INSTANCE_REFLECTION_PROBE: {
+				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
+				scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
+
+			} break;
+			case RS::INSTANCE_PARTICLES_COLLISION: {
+				heightfield_particle_colliders_update_list.erase(instance);
+			} break;
+			case RS::INSTANCE_GI_PROBE: {
+				InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
+
+#ifdef DEBUG_ENABLED
+				if (gi_probe->geometries.size()) {
+					ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe.");
+				}
+#endif
+#ifdef DEBUG_ENABLED
+				if (gi_probe->lights.size()) {
+					ERR_PRINT("BUG, indexing did not unpair lights from GIProbe.");
+				}
+#endif
+
+				if (gi_probe->update_element.in_list()) {
+					gi_probe_update_list.remove(&gi_probe->update_element);
+				}
+			} break;
+			default: {
+			}
+		}
+
+		instance->scenario = nullptr;
+	}
+
+	if (p_scenario.is_valid()) {
+		Scenario *scenario = scenario_owner.getornull(p_scenario);
+		ERR_FAIL_COND(!scenario);
+
+		instance->scenario = scenario;
+
+		scenario->instances.add(&instance->scenario_item);
+
+		switch (instance->base_type) {
+			case RS::INSTANCE_LIGHT: {
+				InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
+
+				if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
+					light->D = scenario->directional_lights.push_back(instance);
+				}
+			} break;
+			case RS::INSTANCE_GI_PROBE: {
+				InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
+				if (!gi_probe->update_element.in_list()) {
+					gi_probe_update_list.add(&gi_probe->update_element);
+				}
+			} break;
+			default: {
+			}
+		}
+
+		_instance_queue_update(instance, true, true);
+	}
+}
+
+void RenderingServerSceneRaster::instance_set_layer_mask(RID p_instance, uint32_t p_mask) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	instance->layer_mask = p_mask;
+}
+
+void RenderingServerSceneRaster::instance_set_transform(RID p_instance, const Transform &p_transform) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	if (instance->transform == p_transform) {
+		return; //must be checked to avoid worst evil
+	}
+
+#ifdef DEBUG_ENABLED
+
+	for (int i = 0; i < 4; i++) {
+		const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin;
+		ERR_FAIL_COND(Math::is_inf(v.x));
+		ERR_FAIL_COND(Math::is_nan(v.x));
+		ERR_FAIL_COND(Math::is_inf(v.y));
+		ERR_FAIL_COND(Math::is_nan(v.y));
+		ERR_FAIL_COND(Math::is_inf(v.z));
+		ERR_FAIL_COND(Math::is_nan(v.z));
+	}
+
+#endif
+	instance->transform = p_transform;
+	_instance_queue_update(instance, true);
+}
+
+void RenderingServerSceneRaster::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	instance->object_id = p_id;
+}
+
+void RenderingServerSceneRaster::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	if (instance->update_item.in_list()) {
+		_update_dirty_instance(instance);
+	}
+
+	ERR_FAIL_INDEX(p_shape, instance->blend_values.size());
+	instance->blend_values.write[p_shape] = p_weight;
+}
+
+void RenderingServerSceneRaster::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	if (instance->base_type == RS::INSTANCE_MESH) {
+		//may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case
+		instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base)));
+	}
+
+	ERR_FAIL_INDEX(p_surface, instance->materials.size());
+
+	instance->materials.write[p_surface] = p_material;
+
+	_instance_queue_update(instance, false, true);
+}
+
+void RenderingServerSceneRaster::instance_set_visible(RID p_instance, bool p_visible) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	if (instance->visible == p_visible) {
+		return;
+	}
+
+	instance->visible = p_visible;
+
+	switch (instance->base_type) {
+		case RS::INSTANCE_LIGHT: {
+			if (RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) {
+				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHT, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
+			}
+
+		} break;
+		case RS::INSTANCE_REFLECTION_PROBE: {
+			if (instance->octree_id && instance->scenario) {
+				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
+			}
+
+		} break;
+		case RS::INSTANCE_DECAL: {
+			if (instance->octree_id && instance->scenario) {
+				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_DECAL, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
+			}
+
+		} break;
+		case RS::INSTANCE_LIGHTMAP: {
+			if (instance->octree_id && instance->scenario) {
+				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0);
+			}
+
+		} break;
+		case RS::INSTANCE_GI_PROBE: {
+			if (instance->octree_id && instance->scenario) {
+				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_GI_PROBE, p_visible ? (RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT)) : 0);
+			}
+
+		} break;
+		case RS::INSTANCE_PARTICLES_COLLISION: {
+			if (instance->octree_id && instance->scenario) {
+				instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_PARTICLES_COLLISION, p_visible ? (1 << RS::INSTANCE_PARTICLES) : 0);
+			}
+
+		} break;
+		default: {
+		}
+	}
+}
+
+inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
+	return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE;
+}
+
+void RenderingServerSceneRaster::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+	ERR_FAIL_COND(!is_geometry_instance(instance->base_type));
+
+	if (p_aabb != AABB()) {
+		// Set custom AABB
+		if (instance->custom_aabb == nullptr) {
+			instance->custom_aabb = memnew(AABB);
+		}
+		*instance->custom_aabb = p_aabb;
+
+	} else {
+		// Clear custom AABB
+		if (instance->custom_aabb != nullptr) {
+			memdelete(instance->custom_aabb);
+			instance->custom_aabb = nullptr;
+		}
+	}
+
+	if (instance->scenario) {
+		_instance_queue_update(instance, true, false);
+	}
+}
+
+void RenderingServerSceneRaster::instance_attach_skeleton(RID p_instance, RID p_skeleton) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	if (instance->skeleton == p_skeleton) {
+		return;
+	}
+
+	instance->skeleton = p_skeleton;
+
+	if (p_skeleton.is_valid()) {
+		//update the dependency now, so if cleared, we remove it
+		RSG::storage->skeleton_update_dependency(p_skeleton, instance);
+	}
+	_instance_queue_update(instance, true, true);
+}
+
+void RenderingServerSceneRaster::instance_set_exterior(RID p_instance, bool p_enabled) {
+}
+
+void RenderingServerSceneRaster::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	instance->extra_margin = p_margin;
+	_instance_queue_update(instance, true, false);
+}
+
+Vector<ObjectID> RenderingServerSceneRaster::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
+	Vector<ObjectID> instances;
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND_V(!scenario, instances);
+
+	const_cast<RenderingServerSceneRaster *>(this)->update_dirty_instances(); // check dirty instances before culling
+
+	int culled = 0;
+	Instance *cull[1024];
+	culled = scenario->octree.cull_aabb(p_aabb, cull, 1024);
+
+	for (int i = 0; i < culled; i++) {
+		Instance *instance = cull[i];
+		ERR_CONTINUE(!instance);
+		if (instance->object_id.is_null()) {
+			continue;
+		}
+
+		instances.push_back(instance->object_id);
+	}
+
+	return instances;
+}
+
+Vector<ObjectID> RenderingServerSceneRaster::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
+	Vector<ObjectID> instances;
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND_V(!scenario, instances);
+	const_cast<RenderingServerSceneRaster *>(this)->update_dirty_instances(); // check dirty instances before culling
+
+	int culled = 0;
+	Instance *cull[1024];
+	culled = scenario->octree.cull_segment(p_from, p_from + p_to * 10000, cull, 1024);
+
+	for (int i = 0; i < culled; i++) {
+		Instance *instance = cull[i];
+		ERR_CONTINUE(!instance);
+		if (instance->object_id.is_null()) {
+			continue;
+		}
+
+		instances.push_back(instance->object_id);
+	}
+
+	return instances;
+}
+
+Vector<ObjectID> RenderingServerSceneRaster::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const {
+	Vector<ObjectID> instances;
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	ERR_FAIL_COND_V(!scenario, instances);
+	const_cast<RenderingServerSceneRaster *>(this)->update_dirty_instances(); // check dirty instances before culling
+
+	int culled = 0;
+	Instance *cull[1024];
+
+	culled = scenario->octree.cull_convex(p_convex, cull, 1024);
+
+	for (int i = 0; i < culled; i++) {
+		Instance *instance = cull[i];
+		ERR_CONTINUE(!instance);
+		if (instance->object_id.is_null()) {
+			continue;
+		}
+
+		instances.push_back(instance->object_id);
+	}
+
+	return instances;
+}
+
+void RenderingServerSceneRaster::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	//ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK));
+
+	switch (p_flags) {
+		case RS::INSTANCE_FLAG_USE_BAKED_LIGHT: {
+			instance->baked_light = p_enabled;
+
+		} break;
+		case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: {
+			if (p_enabled == instance->dynamic_gi) {
+				//bye, redundant
+				return;
+			}
+
+			if (instance->octree_id != 0) {
+				//remove from octree, it needs to be re-paired
+				instance->scenario->octree.erase(instance->octree_id);
+				instance->octree_id = 0;
+				_instance_queue_update(instance, true, true);
+			}
+
+			//once out of octree, can be changed
+			instance->dynamic_gi = p_enabled;
+
+		} break;
+		case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {
+			instance->redraw_if_visible = p_enabled;
+
+		} break;
+		default: {
+		}
+	}
+}
+
+void RenderingServerSceneRaster::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	instance->cast_shadows = p_shadow_casting_setting;
+	_instance_queue_update(instance, false, true);
+}
+
+void RenderingServerSceneRaster::instance_geometry_set_material_override(RID p_instance, RID p_material) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	instance->material_override = p_material;
+	_instance_queue_update(instance, false, true);
+}
+
+void RenderingServerSceneRaster::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
+}
+
+void RenderingServerSceneRaster::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) {
+}
+
+void RenderingServerSceneRaster::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	if (instance->lightmap) {
+		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(((Instance *)instance->lightmap)->base_data);
+		lightmap_data->users.erase(instance);
+		instance->lightmap = nullptr;
+	}
+
+	Instance *lightmap_instance = instance_owner.getornull(p_lightmap);
+
+	instance->lightmap = lightmap_instance;
+	instance->lightmap_uv_scale = p_lightmap_uv_scale;
+	instance->lightmap_slice_index = p_slice_index;
+
+	if (lightmap_instance) {
+		InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data);
+		lightmap_data->users.insert(instance);
+	}
+}
+
+void RenderingServerSceneRaster::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
+	Instance *instance = instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
+
+	if (!E) {
+		RasterizerScene::InstanceBase::InstanceShaderParameter isp;
+		isp.index = -1;
+		isp.info = PropertyInfo();
+		isp.value = p_value;
+		instance->instance_shader_parameters[p_parameter] = isp;
+	} else {
+		E->get().value = p_value;
+		if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) {
+			//update directly
+			RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value);
+		}
+	}
+}
+
+Variant RenderingServerSceneRaster::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const {
+	const Instance *instance = const_cast<RenderingServerSceneRaster *>(this)->instance_owner.getornull(p_instance);
+	ERR_FAIL_COND_V(!instance, Variant());
+
+	if (instance->instance_shader_parameters.has(p_parameter)) {
+		return instance->instance_shader_parameters[p_parameter].value;
+	}
+	return Variant();
+}
+
+Variant RenderingServerSceneRaster::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const {
+	const Instance *instance = const_cast<RenderingServerSceneRaster *>(this)->instance_owner.getornull(p_instance);
+	ERR_FAIL_COND_V(!instance, Variant());
+
+	if (instance->instance_shader_parameters.has(p_parameter)) {
+		return instance->instance_shader_parameters[p_parameter].default_value;
+	}
+	return Variant();
+}
+
+void RenderingServerSceneRaster::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const {
+	const Instance *instance = const_cast<RenderingServerSceneRaster *>(this)->instance_owner.getornull(p_instance);
+	ERR_FAIL_COND(!instance);
+
+	const_cast<RenderingServerSceneRaster *>(this)->update_dirty_instances();
+
+	Vector<StringName> names;
+	for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
+		names.push_back(E->key());
+	}
+	names.sort_custom<StringName::AlphCompare>();
+	for (int i = 0; i < names.size(); i++) {
+		PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info;
+		p_parameters->push_back(pinfo);
+	}
+}
+
+void RenderingServerSceneRaster::_update_instance(Instance *p_instance) {
+	p_instance->version++;
+
+	if (p_instance->base_type == RS::INSTANCE_LIGHT) {
+		InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
+
+		scene_render->light_instance_set_transform(light->instance, p_instance->transform);
+		scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb));
+		light->shadow_dirty = true;
+
+		RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base);
+		if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
+			if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+				p_instance->scenario->dynamic_lights.erase(light->instance);
+			}
+
+			light->bake_mode = bake_mode;
+
+			if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+				p_instance->scenario->dynamic_lights.push_back(light->instance);
+			}
+		}
+
+		uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base);
+		if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
+			light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
+		}
+	}
+
+	if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
+		InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
+
+		scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform);
+		reflection_probe->reflection_dirty = true;
+	}
+
+	if (p_instance->base_type == RS::INSTANCE_DECAL) {
+		InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
+
+		scene_render->decal_instance_set_transform(decal->instance, p_instance->transform);
+	}
+
+	if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
+		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);
+	}
+
+	if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
+		RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
+	}
+
+	if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
+		//remove materials no longer used and un-own them
+		if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) {
+			heightfield_particle_colliders_update_list.insert(p_instance);
+		}
+	}
+
+	if (p_instance->aabb.has_no_surface()) {
+		return;
+	}
+
+	if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+		InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+		//make sure lights are updated if it casts shadow
+
+		if (geom->can_cast_shadows) {
+			for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
+				InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
+				light->shadow_dirty = true;
+			}
+		}
+
+		if (!p_instance->lightmap && geom->lightmap_captures.size()) {
+			//affected by lightmap captures, must update capture info!
+			_update_instance_lightmap_captures(p_instance);
+		} else {
+			if (!p_instance->lightmap_sh.empty()) {
+				p_instance->lightmap_sh.clear(); //don't need SH
+				p_instance->lightmap_target_sh.clear(); //don't need SH
+			}
+		}
+	}
+
+	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 (List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
+			Instance *geom = E->get().geometry;
+			_instance_queue_update(geom, true, false);
+		}
+	}
+
+	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) {
+		return;
+	}
+
+	if (p_instance->octree_id == 0) {
+		uint32_t base_type = 1 << p_instance->base_type;
+		uint32_t pairable_mask = 0;
+		bool pairable = false;
+
+		if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL || p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
+			pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0;
+			pairable = true;
+		}
+
+		if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
+			pairable_mask = p_instance->visible ? (1 << RS::INSTANCE_PARTICLES) : 0;
+			pairable = true;
+		}
+
+		if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
+			//lights and geometries
+			pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT) : 0;
+			pairable = true;
+		}
+
+		// not inside octree
+		p_instance->octree_id = p_instance->scenario->octree.create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask);
+
+	} else {
+		/*
+		if (new_aabb==p_instance->data.transformed_aabb)
+			return;
+		*/
+
+		p_instance->scenario->octree.move(p_instance->octree_id, new_aabb);
+	}
+}
+
+void RenderingServerSceneRaster::_update_instance_aabb(Instance *p_instance) {
+	AABB new_aabb;
+
+	ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_NONE && !p_instance->base.is_valid());
+
+	switch (p_instance->base_type) {
+		case RenderingServer::INSTANCE_NONE: {
+			// do nothing
+		} break;
+		case RenderingServer::INSTANCE_MESH: {
+			if (p_instance->custom_aabb) {
+				new_aabb = *p_instance->custom_aabb;
+			} else {
+				new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
+			}
+
+		} break;
+
+		case RenderingServer::INSTANCE_MULTIMESH: {
+			if (p_instance->custom_aabb) {
+				new_aabb = *p_instance->custom_aabb;
+			} else {
+				new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base);
+			}
+
+		} break;
+		case RenderingServer::INSTANCE_IMMEDIATE: {
+			if (p_instance->custom_aabb) {
+				new_aabb = *p_instance->custom_aabb;
+			} else {
+				new_aabb = RSG::storage->immediate_get_aabb(p_instance->base);
+			}
+
+		} break;
+		case RenderingServer::INSTANCE_PARTICLES: {
+			if (p_instance->custom_aabb) {
+				new_aabb = *p_instance->custom_aabb;
+			} else {
+				new_aabb = RSG::storage->particles_get_aabb(p_instance->base);
+			}
+
+		} break;
+		case RenderingServer::INSTANCE_PARTICLES_COLLISION: {
+			new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
+
+		} break;
+		case RenderingServer::INSTANCE_LIGHT: {
+			new_aabb = RSG::storage->light_get_aabb(p_instance->base);
+
+		} break;
+		case RenderingServer::INSTANCE_REFLECTION_PROBE: {
+			new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
+
+		} break;
+		case RenderingServer::INSTANCE_DECAL: {
+			new_aabb = RSG::storage->decal_get_aabb(p_instance->base);
+
+		} break;
+		case RenderingServer::INSTANCE_GI_PROBE: {
+			new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base);
+
+		} break;
+		case RenderingServer::INSTANCE_LIGHTMAP: {
+			new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base);
+
+		} break;
+		default: {
+		}
+	}
+
+	// <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs
+	if (p_instance->extra_margin) {
+		new_aabb.grow_by(p_instance->extra_margin);
+	}
+
+	p_instance->aabb = new_aabb;
+}
+
+void RenderingServerSceneRaster::_update_instance_lightmap_captures(Instance *p_instance) {
+	bool first_set = p_instance->lightmap_sh.size() == 0;
+	p_instance->lightmap_sh.resize(9); //using SH
+	p_instance->lightmap_target_sh.resize(9); //using SH
+	Color *instance_sh = p_instance->lightmap_target_sh.ptrw();
+	bool inside = false;
+	Color accum_sh[9];
+	float accum_blend = 0.0;
+
+	InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+	for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
+		Instance *lightmap = E->get();
+
+		bool interior = RSG::storage->lightmap_is_interior(lightmap->base);
+
+		if (inside && !interior) {
+			continue; //we are inside, ignore exteriors
+		}
+
+		Transform to_bounds = lightmap->transform.affine_inverse();
+		Vector3 center = p_instance->transform.xform(p_instance->aabb.position + p_instance->aabb.size * 0.5); //use aabb center
+
+		Vector3 lm_pos = to_bounds.xform(center);
+
+		AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base);
+		if (!bounds.has_point(lm_pos)) {
+			continue; //not in this lightmap
+		}
+
+		Color sh[9];
+		RSG::storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);
+
+		//rotate it
+		Basis rot = lightmap->transform.basis.orthonormalized();
+		for (int i = 0; i < 3; i++) {
+			float csh[9];
+			for (int j = 0; j < 9; j++) {
+				csh[j] = sh[j][i];
+			}
+			rot.rotate_sh(csh);
+			for (int j = 0; j < 9; j++) {
+				sh[j][i] = csh[j];
+			}
+		}
+
+		Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0);
+
+		float blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z));
+		//make blend more rounded
+		blend = Math::lerp(inner_pos.length(), blend, blend);
+		blend *= blend;
+		blend = MAX(0.0, 1.0 - blend);
+
+		if (interior && !inside) {
+			//do not blend, just replace
+			for (int j = 0; j < 9; j++) {
+				accum_sh[j] = sh[j] * blend;
+			}
+			accum_blend = blend;
+			inside = true;
+		} else {
+			for (int j = 0; j < 9; j++) {
+				accum_sh[j] += sh[j] * blend;
+			}
+			accum_blend += blend;
+		}
+	}
+
+	if (accum_blend > 0.0) {
+		for (int j = 0; j < 9; j++) {
+			instance_sh[j] = accum_sh[j] / accum_blend;
+			if (first_set) {
+				p_instance->lightmap_sh.write[j] = instance_sh[j];
+			}
+		}
+	}
+}
+
+bool RenderingServerSceneRaster::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario) {
+	InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
+
+	Transform light_transform = p_instance->transform;
+	light_transform.orthonormalize(); //scale does not count on lights
+
+	bool animated_material_found = false;
+
+	switch (RSG::storage->light_get_type(p_instance->base)) {
+		case RS::LIGHT_DIRECTIONAL: {
+			real_t max_distance = p_cam_projection.get_z_far();
+			real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
+			if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
+				max_distance = MIN(shadow_max, max_distance);
+			}
+			max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
+			real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
+
+			RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
+
+			real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+
+			if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) {
+				//optimize min/max
+				Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
+				int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+				Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2));
+				//check distance max and min
+
+				bool found_items = false;
+				real_t z_max = -1e20;
+				real_t z_min = 1e20;
+
+				for (int i = 0; i < cull_count; i++) {
+					Instance *instance = instance_shadow_cull_result[i];
+					if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+						continue;
+					}
+
+					if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+						animated_material_found = true;
+					}
+
+					real_t max, min;
+					instance->transformed_aabb.project_range_in_plane(base, min, max);
+
+					if (max > z_max) {
+						z_max = max;
+					}
+
+					if (min < z_min) {
+						z_min = min;
+					}
+
+					found_items = true;
+				}
+
+				if (found_items) {
+					min_distance = MAX(min_distance, z_min);
+					max_distance = MIN(max_distance, z_max);
+				}
+			}
+
+			real_t range = max_distance - min_distance;
+
+			int splits = 0;
+			switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
+				case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
+					splits = 1;
+					break;
+				case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
+					splits = 2;
+					break;
+				case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
+					splits = 4;
+					break;
+			}
+
+			real_t distances[5];
+
+			distances[0] = min_distance;
+			for (int i = 0; i < splits; i++) {
+				distances[i + 1] = min_distance + RSG::storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
+			};
+
+			distances[splits] = max_distance;
+
+			real_t texture_size = scene_render->get_directional_light_shadow_size(light->instance);
+
+			bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
+
+			real_t first_radius = 0.0;
+
+			real_t min_distance_bias_scale = pancake_size > 0 ? distances[1] / 10.0 : 0;
+
+			for (int i = 0; i < splits; i++) {
+				RENDER_TIMESTAMP("Culling Directional Light split" + itos(i));
+
+				// setup a camera matrix for that range!
+				CameraMatrix camera_matrix;
+
+				real_t aspect = p_cam_projection.get_aspect();
+
+				if (p_cam_orthogonal) {
+					Vector2 vp_he = p_cam_projection.get_viewport_half_extents();
+
+					camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+				} else {
+					real_t fov = p_cam_projection.get_fov(); //this is actually yfov, because set aspect tries to keep it
+					camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
+				}
+
+				//obtain the frustum endpoints
+
+				Vector3 endpoints[8]; // frustum plane endpoints
+				bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints);
+				ERR_CONTINUE(!res);
+
+				// obtain the light frustm ranges (given endpoints)
+
+				Transform transform = light_transform; //discard scale and stabilize light
+
+				Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized();
+				Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized();
+				Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized();
+				//z_vec points agsint the camera, like in default opengl
+
+				real_t x_min = 0.f, x_max = 0.f;
+				real_t y_min = 0.f, y_max = 0.f;
+				real_t z_min = 0.f, z_max = 0.f;
+
+				// FIXME: z_max_cam is defined, computed, but not used below when setting up
+				// ortho_camera. Commented out for now to fix warnings but should be investigated.
+				real_t x_min_cam = 0.f, x_max_cam = 0.f;
+				real_t y_min_cam = 0.f, y_max_cam = 0.f;
+				real_t z_min_cam = 0.f;
+				//real_t z_max_cam = 0.f;
+
+				real_t bias_scale = 1.0;
+				real_t aspect_bias_scale = 1.0;
+
+				//used for culling
+
+				for (int j = 0; j < 8; j++) {
+					real_t d_x = x_vec.dot(endpoints[j]);
+					real_t d_y = y_vec.dot(endpoints[j]);
+					real_t d_z = z_vec.dot(endpoints[j]);
+
+					if (j == 0 || d_x < x_min) {
+						x_min = d_x;
+					}
+					if (j == 0 || d_x > x_max) {
+						x_max = d_x;
+					}
+
+					if (j == 0 || d_y < y_min) {
+						y_min = d_y;
+					}
+					if (j == 0 || d_y > y_max) {
+						y_max = d_y;
+					}
+
+					if (j == 0 || d_z < z_min) {
+						z_min = d_z;
+					}
+					if (j == 0 || d_z > z_max) {
+						z_max = d_z;
+					}
+				}
+
+				real_t radius = 0;
+				real_t soft_shadow_expand = 0;
+				Vector3 center;
+
+				{
+					//camera viewport stuff
+
+					for (int j = 0; j < 8; j++) {
+						center += endpoints[j];
+					}
+					center /= 8.0;
+
+					//center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;
+
+					for (int j = 0; j < 8; j++) {
+						real_t d = center.distance_to(endpoints[j]);
+						if (d > radius) {
+							radius = d;
+						}
+					}
+
+					radius *= texture_size / (texture_size - 2.0); //add a texel by each side
+
+					if (i == 0) {
+						first_radius = radius;
+					} else {
+						bias_scale = radius / first_radius;
+					}
+
+					z_min_cam = z_vec.dot(center) - radius;
+
+					{
+						float soft_shadow_angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);
+
+						if (soft_shadow_angle > 0.0 && pancake_size > 0.0) {
+							float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;
+							soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range;
+
+							x_max += soft_shadow_expand;
+							y_max += soft_shadow_expand;
+
+							x_min -= soft_shadow_expand;
+							y_min -= soft_shadow_expand;
+						}
+					}
+
+					x_max_cam = x_vec.dot(center) + radius + soft_shadow_expand;
+					x_min_cam = x_vec.dot(center) - radius - soft_shadow_expand;
+					y_max_cam = y_vec.dot(center) + radius + soft_shadow_expand;
+					y_min_cam = y_vec.dot(center) - radius - soft_shadow_expand;
+
+					if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
+						//this trick here is what stabilizes the shadow (make potential jaggies to not move)
+						//at the cost of some wasted resolution. Still the quality increase is very well worth it
+
+						real_t unit = radius * 2.0 / texture_size;
+
+						x_max_cam = Math::stepify(x_max_cam, unit);
+						x_min_cam = Math::stepify(x_min_cam, unit);
+						y_max_cam = Math::stepify(y_max_cam, unit);
+						y_min_cam = Math::stepify(y_min_cam, unit);
+					}
+				}
+
+				//now that we now all ranges, we can proceed to make the light frustum planes, for culling octree
+
+				Vector<Plane> light_frustum_planes;
+				light_frustum_planes.resize(6);
+
+				//right/left
+				light_frustum_planes.write[0] = Plane(x_vec, x_max);
+				light_frustum_planes.write[1] = Plane(-x_vec, -x_min);
+				//top/bottom
+				light_frustum_planes.write[2] = Plane(y_vec, y_max);
+				light_frustum_planes.write[3] = Plane(-y_vec, -y_min);
+				//near/far
+				light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6);
+				light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed
+
+				int cull_count = p_scenario->octree.cull_convex(light_frustum_planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+
+				// a pre pass will need to be needed to determine the actual z-near to be used
+
+				Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
+
+				real_t cull_max = 0;
+				for (int j = 0; j < cull_count; j++) {
+					real_t min, max;
+					Instance *instance = instance_shadow_cull_result[j];
+					if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+						cull_count--;
+						SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
+						j--;
+						continue;
+					}
+
+					instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max);
+					instance->depth = near_plane.distance_to(instance->transform.origin);
+					instance->depth_layer = 0;
+					if (j == 0 || max > cull_max) {
+						cull_max = max;
+					}
+				}
+
+				if (cull_max > z_max) {
+					z_max = cull_max;
+				}
+
+				if (pancake_size > 0) {
+					z_max = z_vec.dot(center) + radius + pancake_size;
+				}
+
+				if (aspect != 1.0) {
+					// if the aspect is different, then the radius will become larger.
+					// if this happens, then bias needs to be adjusted too, as depth will increase
+					// to do this, compare the depth of one that would have resulted from a square frustum
+
+					CameraMatrix camera_matrix_square;
+					if (p_cam_orthogonal) {
+						Vector2 vp_he = camera_matrix.get_viewport_half_extents();
+						if (p_cam_vaspect) {
+							camera_matrix_square.set_orthogonal(vp_he.x * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
+						} else {
+							camera_matrix_square.set_orthogonal(vp_he.y * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+						}
+					} else {
+						Vector2 vp_he = camera_matrix.get_viewport_half_extents();
+						if (p_cam_vaspect) {
+							camera_matrix_square.set_frustum(vp_he.x * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true);
+						} else {
+							camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false);
+						}
+					}
+
+					Vector3 endpoints_square[8]; // frustum plane endpoints
+					res = camera_matrix_square.get_endpoints(p_cam_transform, endpoints_square);
+					ERR_CONTINUE(!res);
+					Vector3 center_square;
+					real_t z_max_square = 0;
+
+					for (int j = 0; j < 8; j++) {
+						center_square += endpoints_square[j];
+
+						real_t d_z = z_vec.dot(endpoints_square[j]);
+
+						if (j == 0 || d_z > z_max_square) {
+							z_max_square = d_z;
+						}
+					}
+
+					if (cull_max > z_max_square) {
+						z_max_square = cull_max;
+					}
+
+					center_square /= 8.0;
+
+					real_t radius_square = 0;
+
+					for (int j = 0; j < 8; j++) {
+						real_t d = center_square.distance_to(endpoints_square[j]);
+						if (d > radius_square) {
+							radius_square = d;
+						}
+					}
+
+					radius_square *= texture_size / (texture_size - 2.0); //add a texel by each side
+
+					if (pancake_size > 0) {
+						z_max_square = z_vec.dot(center_square) + radius_square + pancake_size;
+					}
+
+					real_t z_min_cam_square = z_vec.dot(center_square) - radius_square;
+
+					aspect_bias_scale = (z_max - z_min_cam) / (z_max_square - z_min_cam_square);
+
+					// this is not entirely perfect, because the cull-adjusted z-max may be different
+					// but at least it's warranted that it results in a greater bias, so no acne should be present either way.
+					// pancaking also helps with this.
+				}
+
+				{
+					CameraMatrix ortho_camera;
+					real_t half_x = (x_max_cam - x_min_cam) * 0.5;
+					real_t half_y = (y_max_cam - y_min_cam) * 0.5;
+
+					ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam));
+
+					Vector2 uv_scale(1.0 / (x_max_cam - x_min_cam), 1.0 / (y_max_cam - y_min_cam));
+
+					Transform ortho_transform;
+					ortho_transform.basis = transform.basis;
+					ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max;
+
+					{
+						Vector3 max_in_view = p_cam_transform.affine_inverse().xform(z_vec * cull_max);
+						Vector3 dir_in_view = p_cam_transform.xform_inv(z_vec).normalized();
+						cull_max = dir_in_view.dot(max_in_view);
+					}
+
+					scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, z_max - z_min_cam, distances[i + 1], i, radius * 2.0 / texture_size, bias_scale * aspect_bias_scale * min_distance_bias_scale, z_max, uv_scale);
+				}
+
+				scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+			}
+
+		} break;
+		case RS::LIGHT_OMNI: {
+			RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base);
+
+			if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !scene_render->light_instances_can_render_shadow_cube()) {
+				for (int i = 0; i < 2; i++) {
+					//using this one ensures that raster deferred will have it
+					RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i));
+
+					real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+
+					real_t z = i == 0 ? -1 : 1;
+					Vector<Plane> planes;
+					planes.resize(6);
+					planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
+					planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
+					planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
+					planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
+					planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
+					planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0));
+
+					int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+					Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
+
+					for (int j = 0; j < cull_count; j++) {
+						Instance *instance = instance_shadow_cull_result[j];
+						if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+							cull_count--;
+							SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
+							j--;
+						} else {
+							if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+								animated_material_found = true;
+							}
+
+							instance->depth = near_plane.distance_to(instance->transform.origin);
+							instance->depth_layer = 0;
+						}
+					}
+
+					scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
+					scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+				}
+			} else { //shadow cube
+
+				real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+				CameraMatrix cm;
+				cm.set_perspective(90, 1, 0.01, radius);
+
+				for (int i = 0; i < 6; i++) {
+					RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i));
+					//using this one ensures that raster deferred will have it
+
+					static const Vector3 view_normals[6] = {
+						Vector3(+1, 0, 0),
+						Vector3(-1, 0, 0),
+						Vector3(0, -1, 0),
+						Vector3(0, +1, 0),
+						Vector3(0, 0, +1),
+						Vector3(0, 0, -1)
+					};
+					static const Vector3 view_up[6] = {
+						Vector3(0, -1, 0),
+						Vector3(0, -1, 0),
+						Vector3(0, 0, -1),
+						Vector3(0, 0, +1),
+						Vector3(0, -1, 0),
+						Vector3(0, -1, 0)
+					};
+
+					Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
+
+					Vector<Plane> planes = cm.get_projection_planes(xform);
+
+					int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+
+					Plane near_plane(xform.origin, -xform.basis.get_axis(2));
+					for (int j = 0; j < cull_count; j++) {
+						Instance *instance = instance_shadow_cull_result[j];
+						if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+							cull_count--;
+							SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
+							j--;
+						} else {
+							if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+								animated_material_found = true;
+							}
+							instance->depth = near_plane.distance_to(instance->transform.origin);
+							instance->depth_layer = 0;
+						}
+					}
+
+					scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
+					scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+				}
+
+				//restore the regular DP matrix
+				scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
+			}
+
+		} break;
+		case RS::LIGHT_SPOT: {
+			RENDER_TIMESTAMP("Culling Spot Light");
+
+			real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+			real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+
+			CameraMatrix cm;
+			cm.set_perspective(angle * 2.0, 1.0, 0.01, radius);
+
+			Vector<Plane> planes = cm.get_projection_planes(light_transform);
+			int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK);
+
+			Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2));
+			for (int j = 0; j < cull_count; j++) {
+				Instance *instance = instance_shadow_cull_result[j];
+				if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+					cull_count--;
+					SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
+					j--;
+				} else {
+					if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+						animated_material_found = true;
+					}
+					instance->depth = near_plane.distance_to(instance->transform.origin);
+					instance->depth_layer = 0;
+				}
+			}
+
+			scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
+			scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+
+		} break;
+	}
+
+	return animated_material_found;
+}
+
+void RenderingServerSceneRaster::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
+// render to mono camera
+#ifndef _3D_DISABLED
+
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+
+	/* STEP 1 - SETUP CAMERA */
+	CameraMatrix camera_matrix;
+	bool ortho = false;
+
+	switch (camera->type) {
+		case Camera::ORTHOGONAL: {
+			camera_matrix.set_orthogonal(
+					camera->size,
+					p_viewport_size.width / (float)p_viewport_size.height,
+					camera->znear,
+					camera->zfar,
+					camera->vaspect);
+			ortho = true;
+		} break;
+		case Camera::PERSPECTIVE: {
+			camera_matrix.set_perspective(
+					camera->fov,
+					p_viewport_size.width / (float)p_viewport_size.height,
+					camera->znear,
+					camera->zfar,
+					camera->vaspect);
+			ortho = false;
+
+		} break;
+		case Camera::FRUSTUM: {
+			camera_matrix.set_frustum(
+					camera->size,
+					p_viewport_size.width / (float)p_viewport_size.height,
+					camera->offset,
+					camera->znear,
+					camera->zfar,
+					camera->vaspect);
+			ortho = false;
+		} break;
+	}
+
+	RID environment = _render_get_environment(p_camera, p_scenario);
+
+	_prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+	_render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
+#endif
+}
+
+void RenderingServerSceneRaster::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) {
+	// render for AR/VR interface
+
+	Camera *camera = camera_owner.getornull(p_camera);
+	ERR_FAIL_COND(!camera);
+
+	/* SETUP CAMERA, we are ignoring type and FOV here */
+	float aspect = p_viewport_size.width / (float)p_viewport_size.height;
+	CameraMatrix camera_matrix = p_interface->get_projection_for_eye(p_eye, aspect, camera->znear, camera->zfar);
+
+	// We also ignore our camera position, it will have been positioned with a slightly old tracking position.
+	// Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo!
+	Transform world_origin = XRServer::get_singleton()->get_world_origin();
+	Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin);
+
+	RID environment = _render_get_environment(p_camera, p_scenario);
+
+	// For stereo render we only prepare for our left eye and then reuse the outcome for our right eye
+	if (p_eye == XRInterface::EYE_LEFT) {
+		// Center our transform, we assume basis is equal.
+		Transform mono_transform = cam_transform;
+		Transform right_transform = p_interface->get_transform_for_eye(XRInterface::EYE_RIGHT, world_origin);
+		mono_transform.origin += right_transform.origin;
+		mono_transform.origin *= 0.5;
+
+		// We need to combine our projection frustums for culling.
+		// Ideally we should use our clipping planes for this and combine them,
+		// however our shadow map logic uses our projection matrix.
+		// Note: as our left and right frustums should be mirrored, we don't need our right projection matrix.
+
+		// - get some base values we need
+		float eye_dist = (mono_transform.origin - cam_transform.origin).length();
+		float z_near = camera_matrix.get_z_near(); // get our near plane
+		float z_far = camera_matrix.get_z_far(); // get our far plane
+		float width = (2.0 * z_near) / camera_matrix.matrix[0][0];
+		float x_shift = width * camera_matrix.matrix[2][0];
+		float height = (2.0 * z_near) / camera_matrix.matrix[1][1];
+		float y_shift = height * camera_matrix.matrix[2][1];
+
+		// printf("Eye_dist = %f, Near = %f, Far = %f, Width = %f, Shift = %f\n", eye_dist, z_near, z_far, width, x_shift);
+
+		// - calculate our near plane size (horizontal only, right_near is mirrored)
+		float left_near = -eye_dist - ((width - x_shift) * 0.5);
+
+		// - calculate our far plane size (horizontal only, right_far is mirrored)
+		float left_far = -eye_dist - (z_far * (width - x_shift) * 0.5 / z_near);
+		float left_far_right_eye = eye_dist - (z_far * (width + x_shift) * 0.5 / z_near);
+		if (left_far > left_far_right_eye) {
+			// on displays smaller then double our iod, the right eye far frustrum can overtake the left eyes.
+			left_far = left_far_right_eye;
+		}
+
+		// - figure out required z-shift
+		float slope = (left_far - left_near) / (z_far - z_near);
+		float z_shift = (left_near / slope) - z_near;
+
+		// - figure out new vertical near plane size (this will be slightly oversized thanks to our z-shift)
+		float top_near = (height - y_shift) * 0.5;
+		top_near += (top_near / z_near) * z_shift;
+		float bottom_near = -(height + y_shift) * 0.5;
+		bottom_near += (bottom_near / z_near) * z_shift;
+
+		// printf("Left_near = %f, Left_far = %f, Top_near = %f, Bottom_near = %f, Z_shift = %f\n", left_near, left_far, top_near, bottom_near, z_shift);
+
+		// - generate our frustum
+		CameraMatrix combined_matrix;
+		combined_matrix.set_frustum(left_near, -left_near, bottom_near, top_near, z_near + z_shift, z_far + z_shift);
+
+		// and finally move our camera back
+		Transform apply_z_shift;
+		apply_z_shift.origin = Vector3(0.0, 0.0, z_shift); // z negative is forward so this moves it backwards
+		mono_transform *= apply_z_shift;
+
+		// now prepare our scene with our adjusted transform projection matrix
+		_prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+	} else if (p_eye == XRInterface::EYE_MONO) {
+		// For mono render, prepare as per usual
+		_prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
+	}
+
+	// And render our scene...
+	_render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1);
+};
+
+void RenderingServerSceneRaster::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) {
+	// Note, in stereo rendering:
+	// - p_cam_transform will be a transform in the middle of our two eyes
+	// - p_cam_projection is a wider frustrum that encompasses both eyes
+
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+
+	render_pass++;
+	uint32_t camera_layer_mask = p_visible_layers;
+
+	scene_render->set_scene_pass(render_pass);
+
+	if (p_render_buffers.is_valid()) {
+		scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not)
+	}
+
+	RENDER_TIMESTAMP("Frustum Culling");
+
+	//rasterizer->set_camera(camera->transform, camera_matrix,ortho);
+
+	Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
+
+	Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized());
+	float z_far = p_cam_projection.get_z_far();
+
+	/* STEP 2 - CULL */
+	instance_cull_count = scenario->octree.cull_convex(planes, instance_cull_result, MAX_INSTANCE_CULL);
+	light_cull_count = 0;
+
+	reflection_probe_cull_count = 0;
+	decal_cull_count = 0;
+	gi_probe_cull_count = 0;
+	lightmap_cull_count = 0;
+
+	//light_samplers_culled=0;
+
+	/*
+	print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0));
+	print_line("OTO: "+itos(p_scenario->octree.get_octant_count()));
+	print_line("OTE: "+itos(p_scenario->octree.get_elem_count()));
+	print_line("OTP: "+itos(p_scenario->octree.get_pair_count()));
+	*/
+
+	/* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */
+	//removed, will replace with culling
+
+	/* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */
+	uint64_t frame_number = RSG::rasterizer->get_frame_number();
+	float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
+
+	for (int i = 0; i < instance_cull_count; i++) {
+		Instance *ins = instance_cull_result[i];
+
+		bool keep = false;
+
+		if ((camera_layer_mask & ins->layer_mask) == 0) {
+			//failure
+		} else if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
+			if (light_cull_count < MAX_LIGHTS_CULLED) {
+				InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
+
+				if (!light->geometries.empty()) {
+					//do not add this light if no geometry is affected by it..
+					light_cull_result[light_cull_count] = ins;
+					light_instance_cull_result[light_cull_count] = light->instance;
+					if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(ins->base)) {
+						scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later
+					}
+
+					light_cull_count++;
+				}
+			}
+		} else if (ins->base_type == RS::INSTANCE_REFLECTION_PROBE && ins->visible) {
+			if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) {
+				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data);
+
+				if (p_reflection_probe != reflection_probe->instance) {
+					//avoid entering The Matrix
+
+					if (!reflection_probe->geometries.empty()) {
+						//do not add this light if no geometry is affected by it..
+
+						if (reflection_probe->reflection_dirty || scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) {
+							if (!reflection_probe->update_list.in_list()) {
+								reflection_probe->render_step = 0;
+								reflection_probe_render_list.add_last(&reflection_probe->update_list);
+							}
+
+							reflection_probe->reflection_dirty = false;
+						}
+
+						if (scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
+							reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
+							reflection_probe_cull_count++;
+						}
+					}
+				}
+			}
+		} else if (ins->base_type == RS::INSTANCE_DECAL && ins->visible) {
+			if (decal_cull_count < MAX_DECALS_CULLED) {
+				InstanceDecalData *decal = static_cast<InstanceDecalData *>(ins->base_data);
+
+				if (!decal->geometries.empty()) {
+					//do not add this decal if no geometry is affected by it..
+					decal_instance_cull_result[decal_cull_count] = decal->instance;
+					decal_cull_count++;
+				}
+			}
+
+		} else if (ins->base_type == RS::INSTANCE_GI_PROBE && ins->visible) {
+			InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(ins->base_data);
+			if (!gi_probe->update_element.in_list()) {
+				gi_probe_update_list.add(&gi_probe->update_element);
+			}
+
+			if (gi_probe_cull_count < MAX_GI_PROBES_CULLED) {
+				gi_probe_instance_cull_result[gi_probe_cull_count] = gi_probe->probe_instance;
+				gi_probe_cull_count++;
+			}
+		} else if (ins->base_type == RS::INSTANCE_LIGHTMAP && ins->visible) {
+			if (lightmap_cull_count < MAX_LIGHTMAPS_CULLED) {
+				lightmap_cull_result[lightmap_cull_count] = ins;
+				lightmap_cull_count++;
+			}
+
+		} else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+			keep = true;
+
+			InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data);
+
+			if (ins->redraw_if_visible) {
+				RenderingServerDefault::redraw_request();
+			}
+
+			if (ins->base_type == RS::INSTANCE_PARTICLES) {
+				//particles visible? process them
+				if (RSG::storage->particles_is_inactive(ins->base)) {
+					//but if nothing is going on, don't do it.
+					keep = false;
+				} else {
+					RSG::storage->particles_request_process(ins->base);
+					RSG::storage->particles_set_view_axis(ins->base, -p_cam_transform.basis.get_axis(2).normalized());
+					//particles visible? request redraw
+					RenderingServerDefault::redraw_request();
+				}
+			}
+
+			if (geom->lighting_dirty) {
+				int l = 0;
+				//only called when lights AABB enter/exit this geometry
+				ins->light_instances.resize(geom->lighting.size());
+
+				for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
+					InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
+
+					ins->light_instances.write[l++] = light->instance;
+				}
+
+				geom->lighting_dirty = false;
+			}
+
+			if (geom->reflection_dirty) {
+				int l = 0;
+				//only called when reflection probe AABB enter/exit this geometry
+				ins->reflection_probe_instances.resize(geom->reflection_probes.size());
+
+				for (List<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
+					InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
+
+					ins->reflection_probe_instances.write[l++] = reflection_probe->instance;
+				}
+
+				geom->reflection_dirty = false;
+			}
+
+			if (geom->gi_probes_dirty) {
+				int l = 0;
+				//only called when reflection probe AABB enter/exit this geometry
+				ins->gi_probe_instances.resize(geom->gi_probes.size());
+
+				for (List<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
+					InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
+
+					ins->gi_probe_instances.write[l++] = gi_probe->probe_instance;
+				}
+
+				geom->gi_probes_dirty = false;
+			}
+
+			if (ins->last_frame_pass != frame_number && !ins->lightmap_target_sh.empty() && !ins->lightmap_sh.empty()) {
+				Color *sh = ins->lightmap_sh.ptrw();
+				const Color *target_sh = ins->lightmap_target_sh.ptr();
+				for (uint32_t j = 0; j < 9; j++) {
+					sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
+				}
+			}
+
+			ins->depth = near_plane.distance_to(ins->transform.origin);
+			ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15);
+		}
+
+		if (!keep) {
+			// remove, no reason to keep
+			instance_cull_count--;
+			SWAP(instance_cull_result[i], instance_cull_result[instance_cull_count]);
+			i--;
+			ins->last_render_pass = 0; // make invalid
+		} else {
+			ins->last_render_pass = render_pass;
+		}
+		ins->last_frame_pass = frame_number;
+	}
+
+	/* STEP 5 - PROCESS LIGHTS */
+
+	RID *directional_light_ptr = &light_instance_cull_result[light_cull_count];
+	directional_light_count = 0;
+
+	// directional lights
+	{
+		Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size());
+		int directional_shadow_count = 0;
+
+		for (List<Instance *>::Element *E = scenario->directional_lights.front(); E; E = E->next()) {
+			if (light_cull_count + directional_light_count >= MAX_LIGHTS_CULLED) {
+				break;
+			}
+
+			if (!E->get()->visible) {
+				continue;
+			}
+
+			InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
+
+			//check shadow..
+
+			if (light) {
+				if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base) && !(RSG::storage->light_get_type(E->get()->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->get()->base))) {
+					lights_with_shadow[directional_shadow_count++] = E->get();
+				}
+				//add to list
+				directional_light_ptr[directional_light_count++] = light->instance;
+			}
+		}
+
+		scene_render->set_directional_shadow_count(directional_shadow_count);
+
+		for (int i = 0; i < directional_shadow_count; i++) {
+			RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i));
+
+			_light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
+
+			RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i));
+		}
+	}
+
+	if (p_using_shadows) { //setup shadow maps
+
+		//SortArray<Instance*,_InstanceLightsort> sorter;
+		//sorter.sort(light_cull_result,light_cull_count);
+		for (int i = 0; i < light_cull_count; i++) {
+			Instance *ins = light_cull_result[i];
+
+			if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
+				continue;
+			}
+
+			InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
+
+			float coverage = 0.f;
+
+			{ //compute coverage
+
+				Transform cam_xf = p_cam_transform;
+				float zn = p_cam_projection.get_z_near();
+				Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane
+
+				// near plane half width and height
+				Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents();
+
+				switch (RSG::storage->light_get_type(ins->base)) {
+					case RS::LIGHT_OMNI: {
+						float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
+
+						//get two points parallel to near plane
+						Vector3 points[2] = {
+							ins->transform.origin,
+							ins->transform.origin + cam_xf.basis.get_axis(0) * radius
+						};
+
+						if (!p_cam_orthogonal) {
+							//if using perspetive, map them to near plane
+							for (int j = 0; j < 2; j++) {
+								if (p.distance_to(points[j]) < 0) {
+									points[j].z = -zn; //small hack to keep size constant when hitting the screen
+								}
+
+								p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane
+							}
+						}
+
+						float screen_diameter = points[0].distance_to(points[1]) * 2;
+						coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
+					} break;
+					case RS::LIGHT_SPOT: {
+						float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
+						float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+
+						float w = radius * Math::sin(Math::deg2rad(angle));
+						float d = radius * Math::cos(Math::deg2rad(angle));
+
+						Vector3 base = ins->transform.origin - ins->transform.basis.get_axis(2).normalized() * d;
+
+						Vector3 points[2] = {
+							base,
+							base + cam_xf.basis.get_axis(0) * w
+						};
+
+						if (!p_cam_orthogonal) {
+							//if using perspetive, map them to near plane
+							for (int j = 0; j < 2; j++) {
+								if (p.distance_to(points[j]) < 0) {
+									points[j].z = -zn; //small hack to keep size constant when hitting the screen
+								}
+
+								p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane
+							}
+						}
+
+						float screen_diameter = points[0].distance_to(points[1]) * 2;
+						coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
+
+					} break;
+					default: {
+						ERR_PRINT("Invalid Light Type");
+					}
+				}
+			}
+
+			if (light->shadow_dirty) {
+				light->last_version++;
+				light->shadow_dirty = false;
+			}
+
+			bool redraw = scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version);
+
+			if (redraw) {
+				//must redraw!
+				RENDER_TIMESTAMP(">Rendering Light " + itos(i));
+				light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario);
+				RENDER_TIMESTAMP("<Rendering Light " + itos(i));
+			}
+		}
+	}
+
+	/* UPDATE SDFGI */
+
+	if (p_render_buffers.is_valid()) {
+		uint32_t cascade_index[8];
+		uint32_t cascade_sizes[8];
+		const RID *cascade_ptrs[8];
+		uint32_t cascade_count = 0;
+		uint32_t sdfgi_light_cull_count = 0;
+
+		uint32_t prev_cascade = 0xFFFFFFFF;
+		for (int i = 0; i < scene_render->sdfgi_get_pending_region_count(p_render_buffers); i++) {
+			AABB region = scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i);
+			uint32_t region_cascade = scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i);
+
+			if (region_cascade != prev_cascade) {
+				cascade_sizes[cascade_count] = 0;
+				cascade_index[cascade_count] = region_cascade;
+				cascade_ptrs[cascade_count] = &sdfgi_light_cull_result[sdfgi_light_cull_count];
+				cascade_count++;
+				sdfgi_light_cull_pass++;
+				prev_cascade = region_cascade;
+			}
+			uint32_t sdfgi_cull_count = scenario->octree.cull_aabb(region, instance_shadow_cull_result, MAX_INSTANCE_CULL);
+
+			for (uint32_t j = 0; j < sdfgi_cull_count; j++) {
+				Instance *ins = instance_shadow_cull_result[j];
+
+				bool keep = false;
+
+				if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) {
+					InstanceLightData *instance_light = (InstanceLightData *)ins->base_data;
+					if (instance_light->bake_mode != RS::LIGHT_BAKE_STATIC || region_cascade > instance_light->max_sdfgi_cascade) {
+						continue;
+					}
+
+					if (sdfgi_light_cull_pass != instance_light->sdfgi_cascade_light_pass && sdfgi_light_cull_count < MAX_LIGHTS_CULLED) {
+						instance_light->sdfgi_cascade_light_pass = sdfgi_light_cull_pass;
+						sdfgi_light_cull_result[sdfgi_light_cull_count++] = instance_light->instance;
+						cascade_sizes[cascade_count - 1]++;
+					}
+				} else if ((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+					if (ins->baked_light) {
+						keep = true;
+					}
+				}
+
+				if (!keep) {
+					// remove, no reason to keep
+					sdfgi_cull_count--;
+					SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[sdfgi_cull_count]);
+					j--;
+				}
+			}
+
+			scene_render->render_sdfgi(p_render_buffers, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, sdfgi_cull_count);
+			//have to save updated cascades, then update static lights.
+		}
+
+		if (sdfgi_light_cull_count) {
+			scene_render->render_sdfgi_static_lights(p_render_buffers, cascade_count, cascade_index, cascade_ptrs, cascade_sizes);
+		}
+
+		scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_light_ptr, directional_light_count, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size());
+	}
+}
+
+RID RenderingServerSceneRaster::_render_get_environment(RID p_camera, RID p_scenario) {
+	Camera *camera = camera_owner.getornull(p_camera);
+	if (camera && scene_render->is_environment(camera->env)) {
+		return camera->env;
+	}
+
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+	if (!scenario) {
+		return RID();
+	}
+	if (scene_render->is_environment(scenario->environment)) {
+		return scenario->environment;
+	}
+
+	if (scene_render->is_environment(scenario->fallback_environment)) {
+		return scenario->fallback_environment;
+	}
+
+	return RID();
+}
+
+void RenderingServerSceneRaster::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+
+	RID camera_effects;
+	if (p_force_camera_effects.is_valid()) {
+		camera_effects = p_force_camera_effects;
+	} else {
+		camera_effects = scenario->camera_effects;
+	}
+	/* PROCESS GEOMETRY AND DRAW SCENE */
+
+	RENDER_TIMESTAMP("Render Scene ");
+	scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
+}
+
+void RenderingServerSceneRaster::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
+#ifndef _3D_DISABLED
+
+	Scenario *scenario = scenario_owner.getornull(p_scenario);
+
+	RID environment;
+	if (scenario->environment.is_valid()) {
+		environment = scenario->environment;
+	} else {
+		environment = scenario->fallback_environment;
+	}
+	RENDER_TIMESTAMP("Render Empty Scene ");
+	scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
+#endif
+}
+
+bool RenderingServerSceneRaster::_render_reflection_probe_step(Instance *p_instance, int p_step) {
+	InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
+	Scenario *scenario = p_instance->scenario;
+	ERR_FAIL_COND_V(!scenario, true);
+
+	RenderingServerDefault::redraw_request(); //update, so it updates in editor
+
+	if (p_step == 0) {
+		if (!scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
+			return true; //all full
+		}
+	}
+
+	if (p_step >= 0 && p_step < 6) {
+		static const Vector3 view_normals[6] = {
+			Vector3(+1, 0, 0),
+			Vector3(-1, 0, 0),
+			Vector3(0, +1, 0),
+			Vector3(0, -1, 0),
+			Vector3(0, 0, +1),
+			Vector3(0, 0, -1)
+		};
+		static const Vector3 view_up[6] = {
+			Vector3(0, -1, 0),
+			Vector3(0, -1, 0),
+			Vector3(0, 0, +1),
+			Vector3(0, 0, -1),
+			Vector3(0, -1, 0),
+			Vector3(0, -1, 0)
+		};
+
+		Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base);
+		Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base);
+		float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
+
+		Vector3 edge = view_normals[p_step] * extents;
+		float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
+
+		max_distance = MAX(max_distance, distance);
+
+		//render cubemap side
+		CameraMatrix cm;
+		cm.set_perspective(90, 1, 0.01, max_distance);
+
+		Transform local_view;
+		local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]);
+
+		Transform xform = p_instance->transform * local_view;
+
+		RID shadow_atlas;
+
+		bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base);
+		if (use_shadows) {
+			shadow_atlas = scenario->reflection_probe_shadow_atlas;
+		}
+
+		RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
+		_prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
+		_render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
+
+	} else {
+		//do roughness postprocess step until it believes it's done
+		RENDER_TIMESTAMP("Post-Process Reflection Probe, Step " + itos(p_step));
+		return scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance);
+	}
+
+	return false;
+}
+
+void RenderingServerSceneRaster::render_probes() {
+	/* REFLECTION PROBES */
+
+	SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first();
+
+	bool busy = false;
+
+	while (ref_probe) {
+		SelfList<InstanceReflectionProbeData> *next = ref_probe->next();
+		RID base = ref_probe->self()->owner->base;
+
+		switch (RSG::storage->reflection_probe_get_update_mode(base)) {
+			case RS::REFLECTION_PROBE_UPDATE_ONCE: {
+				if (busy) { //already rendering something
+					break;
+				}
+
+				bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step);
+				if (done) {
+					reflection_probe_render_list.remove(ref_probe);
+				} else {
+					ref_probe->self()->render_step++;
+				}
+
+				busy = true; //do not render another one of this kind
+			} break;
+			case RS::REFLECTION_PROBE_UPDATE_ALWAYS: {
+				int step = 0;
+				bool done = false;
+				while (!done) {
+					done = _render_reflection_probe_step(ref_probe->self()->owner, step);
+					step++;
+				}
+
+				reflection_probe_render_list.remove(ref_probe);
+			} break;
+		}
+
+		ref_probe = next;
+	}
+
+	/* GI PROBES */
+
+	SelfList<InstanceGIProbeData> *gi_probe = gi_probe_update_list.first();
+
+	if (gi_probe) {
+		RENDER_TIMESTAMP("Render GI Probes");
+	}
+
+	while (gi_probe) {
+		SelfList<InstanceGIProbeData> *next = gi_probe->next();
+
+		InstanceGIProbeData *probe = gi_probe->self();
+		//Instance *instance_probe = probe->owner;
+
+		//check if probe must be setup, but don't do if on the lighting thread
+
+		bool cache_dirty = false;
+		int cache_count = 0;
+		{
+			int light_cache_size = probe->light_cache.size();
+			const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr();
+			const RID *instance_caches = probe->light_instances.ptr();
+
+			int idx = 0; //must count visible lights
+			for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) {
+				Instance *instance = E->get();
+				InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
+				if (!instance->visible) {
+					continue;
+				}
+				if (cache_dirty) {
+					//do nothing, since idx must count all visible lights anyway
+				} else if (idx >= light_cache_size) {
+					cache_dirty = true;
+				} else {
+					const InstanceGIProbeData::LightCache *cache = &caches[idx];
+
+					if (
+							instance_caches[idx] != instance_light->instance ||
+							cache->has_shadow != RSG::storage->light_has_shadow(instance->base) ||
+							cache->type != RSG::storage->light_get_type(instance->base) ||
+							cache->transform != instance->transform ||
+							cache->color != RSG::storage->light_get_color(instance->base) ||
+							cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+							cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
+							cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
+							cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
+							cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
+							cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {
+						cache_dirty = true;
+					}
+				}
+
+				idx++;
+			}
+
+			for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) {
+				Instance *instance = E->get();
+				InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
+				if (!instance->visible) {
+					continue;
+				}
+				if (cache_dirty) {
+					//do nothing, since idx must count all visible lights anyway
+				} else if (idx >= light_cache_size) {
+					cache_dirty = true;
+				} else {
+					const InstanceGIProbeData::LightCache *cache = &caches[idx];
+
+					if (
+							instance_caches[idx] != instance_light->instance ||
+							cache->has_shadow != RSG::storage->light_has_shadow(instance->base) ||
+							cache->type != RSG::storage->light_get_type(instance->base) ||
+							cache->transform != instance->transform ||
+							cache->color != RSG::storage->light_get_color(instance->base) ||
+							cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+							cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
+							cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
+							cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
+							cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
+							cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||
+							cache->sky_only != RSG::storage->light_directional_is_sky_only(instance->base)) {
+						cache_dirty = true;
+					}
+				}
+
+				idx++;
+			}
+
+			if (idx != light_cache_size) {
+				cache_dirty = true;
+			}
+
+			cache_count = idx;
+		}
+
+		bool update_lights = scene_render->gi_probe_needs_update(probe->probe_instance);
+
+		if (cache_dirty) {
+			probe->light_cache.resize(cache_count);
+			probe->light_instances.resize(cache_count);
+
+			if (cache_count) {
+				InstanceGIProbeData::LightCache *caches = probe->light_cache.ptrw();
+				RID *instance_caches = probe->light_instances.ptrw();
+
+				int idx = 0; //must count visible lights
+				for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) {
+					Instance *instance = E->get();
+					InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
+					if (!instance->visible) {
+						continue;
+					}
+
+					InstanceGIProbeData::LightCache *cache = &caches[idx];
+
+					instance_caches[idx] = instance_light->instance;
+					cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
+					cache->type = RSG::storage->light_get_type(instance->base);
+					cache->transform = instance->transform;
+					cache->color = RSG::storage->light_get_color(instance->base);
+					cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+					cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+					cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
+					cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
+					cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+					cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+
+					idx++;
+				}
+				for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) {
+					Instance *instance = E->get();
+					InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
+					if (!instance->visible) {
+						continue;
+					}
+
+					InstanceGIProbeData::LightCache *cache = &caches[idx];
+
+					instance_caches[idx] = instance_light->instance;
+					cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
+					cache->type = RSG::storage->light_get_type(instance->base);
+					cache->transform = instance->transform;
+					cache->color = RSG::storage->light_get_color(instance->base);
+					cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+					cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+					cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
+					cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
+					cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+					cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+					cache->sky_only = RSG::storage->light_directional_is_sky_only(instance->base);
+
+					idx++;
+				}
+			}
+
+			update_lights = true;
+		}
+
+		instance_cull_count = 0;
+		for (List<InstanceGIProbeData::PairInfo>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) {
+			if (instance_cull_count < MAX_INSTANCE_CULL) {
+				Instance *ins = E->get().geometry;
+				if (!ins->visible) {
+					continue;
+				}
+				InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;
+
+				if (geom->gi_probes_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());
+
+					for (List<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
+						InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
+
+						ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance;
+					}
+
+					geom->gi_probes_dirty = false;
+				}
+
+				instance_cull_result[instance_cull_count++] = E->get().geometry;
+			}
+		}
+
+		scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, instance_cull_count, (RasterizerScene::InstanceBase **)instance_cull_result);
+
+		gi_probe_update_list.remove(gi_probe);
+
+		gi_probe = next;
+	}
+}
+
+void RenderingServerSceneRaster::render_particle_colliders() {
+	while (heightfield_particle_colliders_update_list.front()) {
+		Instance *hfpc = heightfield_particle_colliders_update_list.front()->get();
+
+		if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
+			//update heightfield
+			int cull_count = hfpc->scenario->octree.cull_aabb(hfpc->transformed_aabb, instance_cull_result, MAX_INSTANCE_CULL); //@TODO: cull mask missing
+			for (int i = 0; i < cull_count; i++) {
+				Instance *instance = instance_cull_result[i];
+				if (!instance->visible || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision
+					cull_count--;
+					SWAP(instance_cull_result[i], instance_cull_result[cull_count]);
+				}
+			}
+
+			scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, (RasterizerScene::InstanceBase **)instance_cull_result, cull_count);
+		}
+		heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front());
+	}
+}
+
+void RenderingServerSceneRaster::_update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material) {
+	List<RasterizerStorage::InstanceShaderParam> plist;
+	RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
+	for (List<RasterizerStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) {
+		StringName name = E->get().info.name;
+		if (isparams.has(name)) {
+			if (isparams[name].info.type != E->get().info.type) {
+				WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different data types. Only the first one (in order) will display correctly.");
+			}
+			if (isparams[name].index != E->get().index) {
+				WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different indices. Only the first one (in order) will display correctly.");
+			}
+			continue; //first one found always has priority
+		}
+
+		RasterizerScene::InstanceBase::InstanceShaderParameter isp;
+		isp.index = E->get().index;
+		isp.info = E->get().info;
+		isp.default_value = E->get().default_value;
+		if (existing_isparams.has(name)) {
+			isp.value = existing_isparams[name].value;
+		} else {
+			isp.value = E->get().default_value;
+		}
+		isparams[name] = isp;
+	}
+}
+
+void RenderingServerSceneRaster::_update_dirty_instance(Instance *p_instance) {
+	if (p_instance->update_aabb) {
+		_update_instance_aabb(p_instance);
+	}
+
+	if (p_instance->update_dependencies) {
+		p_instance->instance_increase_version();
+
+		if (p_instance->base.is_valid()) {
+			RSG::storage->base_update_dependency(p_instance->base, p_instance);
+		}
+
+		if (p_instance->material_override.is_valid()) {
+			RSG::storage->material_update_dependency(p_instance->material_override, p_instance);
+		}
+
+		if (p_instance->base_type == RS::INSTANCE_MESH) {
+			//remove materials no longer used and un-own them
+
+			int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base);
+			p_instance->materials.resize(new_mat_count);
+
+			int new_blend_shape_count = RSG::storage->mesh_get_blend_shape_count(p_instance->base);
+			if (new_blend_shape_count != p_instance->blend_values.size()) {
+				p_instance->blend_values.resize(new_blend_shape_count);
+				for (int i = 0; i < new_blend_shape_count; i++) {
+					p_instance->blend_values.write[i] = 0;
+				}
+			}
+		}
+
+		if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+			InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+
+			bool can_cast_shadows = true;
+			bool is_animated = false;
+			Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> isparams;
+
+			if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
+				can_cast_shadows = false;
+			}
+
+			if (p_instance->material_override.is_valid()) {
+				if (!RSG::storage->material_casts_shadows(p_instance->material_override)) {
+					can_cast_shadows = false;
+				}
+				is_animated = RSG::storage->material_is_animated(p_instance->material_override);
+				_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override);
+			} else {
+				if (p_instance->base_type == RS::INSTANCE_MESH) {
+					RID mesh = p_instance->base;
+
+					if (mesh.is_valid()) {
+						bool cast_shadows = false;
+
+						for (int i = 0; i < p_instance->materials.size(); i++) {
+							RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i);
+
+							if (!mat.is_valid()) {
+								cast_shadows = true;
+							} else {
+								if (RSG::storage->material_casts_shadows(mat)) {
+									cast_shadows = true;
+								}
+
+								if (RSG::storage->material_is_animated(mat)) {
+									is_animated = true;
+								}
+
+								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+
+								RSG::storage->material_update_dependency(mat, p_instance);
+							}
+						}
+
+						if (!cast_shadows) {
+							can_cast_shadows = false;
+						}
+					}
+
+				} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {
+					RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base);
+					if (mesh.is_valid()) {
+						bool cast_shadows = false;
+
+						int sc = RSG::storage->mesh_get_surface_count(mesh);
+						for (int i = 0; i < sc; i++) {
+							RID mat = RSG::storage->mesh_surface_get_material(mesh, i);
+
+							if (!mat.is_valid()) {
+								cast_shadows = true;
+
+							} else {
+								if (RSG::storage->material_casts_shadows(mat)) {
+									cast_shadows = true;
+								}
+								if (RSG::storage->material_is_animated(mat)) {
+									is_animated = true;
+								}
+
+								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+
+								RSG::storage->material_update_dependency(mat, p_instance);
+							}
+						}
+
+						if (!cast_shadows) {
+							can_cast_shadows = false;
+						}
+
+						RSG::storage->base_update_dependency(mesh, p_instance);
+					}
+				} else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) {
+					RID mat = RSG::storage->immediate_get_material(p_instance->base);
+
+					if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) {
+						can_cast_shadows = false;
+					}
+
+					if (mat.is_valid() && RSG::storage->material_is_animated(mat)) {
+						is_animated = true;
+					}
+
+					if (mat.is_valid()) {
+						_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+					}
+
+					if (mat.is_valid()) {
+						RSG::storage->material_update_dependency(mat, p_instance);
+					}
+
+				} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
+					bool cast_shadows = false;
+
+					int dp = RSG::storage->particles_get_draw_passes(p_instance->base);
+
+					for (int i = 0; i < dp; i++) {
+						RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i);
+						if (!mesh.is_valid()) {
+							continue;
+						}
+
+						int sc = RSG::storage->mesh_get_surface_count(mesh);
+						for (int j = 0; j < sc; j++) {
+							RID mat = RSG::storage->mesh_surface_get_material(mesh, j);
+
+							if (!mat.is_valid()) {
+								cast_shadows = true;
+							} else {
+								if (RSG::storage->material_casts_shadows(mat)) {
+									cast_shadows = true;
+								}
+
+								if (RSG::storage->material_is_animated(mat)) {
+									is_animated = true;
+								}
+
+								_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+
+								RSG::storage->material_update_dependency(mat, p_instance);
+							}
+						}
+					}
+
+					if (!cast_shadows) {
+						can_cast_shadows = false;
+					}
+				}
+			}
+
+			if (can_cast_shadows != geom->can_cast_shadows) {
+				//ability to cast shadows change, let lights now
+				for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
+					InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
+					light->shadow_dirty = true;
+				}
+
+				geom->can_cast_shadows = can_cast_shadows;
+			}
+
+			geom->material_is_animated = is_animated;
+			p_instance->instance_shader_parameters = isparams;
+
+			if (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) {
+					p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
+					for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
+						if (E->get().value.get_type() != Variant::NIL) {
+							RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value);
+						}
+					}
+				} else {
+					RSG::storage->global_variables_instance_free(p_instance->self);
+					p_instance->instance_allocated_shader_parameters_offset = -1;
+				}
+			}
+		}
+
+		if (p_instance->skeleton.is_valid()) {
+			RSG::storage->skeleton_update_dependency(p_instance->skeleton, p_instance);
+		}
+
+		p_instance->clean_up_dependencies();
+	}
+
+	_instance_update_list.remove(&p_instance->update_item);
+
+	_update_instance(p_instance);
+
+	p_instance->update_aabb = false;
+	p_instance->update_dependencies = false;
+}
+
+void RenderingServerSceneRaster::update_dirty_instances() {
+	RSG::storage->update_dirty_resources();
+
+	while (_instance_update_list.first()) {
+		_update_dirty_instance(_instance_update_list.first()->self());
+	}
+}
+
+void RenderingServerSceneRaster::update() {
+	scene_render->update();
+	update_dirty_instances();
+	render_particle_colliders();
+}
+
+bool RenderingServerSceneRaster::free(RID p_rid) {
+	if (scene_render->free(p_rid)) {
+		return true;
+	}
+
+	if (camera_owner.owns(p_rid)) {
+		Camera *camera = camera_owner.getornull(p_rid);
+
+		camera_owner.free(p_rid);
+		memdelete(camera);
+
+	} else if (scenario_owner.owns(p_rid)) {
+		Scenario *scenario = scenario_owner.getornull(p_rid);
+
+		while (scenario->instances.first()) {
+			instance_set_scenario(scenario->instances.first()->self()->self, RID());
+		}
+		scene_render->free(scenario->reflection_probe_shadow_atlas);
+		scene_render->free(scenario->reflection_atlas);
+		scenario_owner.free(p_rid);
+		memdelete(scenario);
+
+	} else if (instance_owner.owns(p_rid)) {
+		// delete the instance
+
+		update_dirty_instances();
+
+		Instance *instance = instance_owner.getornull(p_rid);
+
+		instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0);
+		instance_set_scenario(p_rid, RID());
+		instance_set_base(p_rid, RID());
+		instance_geometry_set_material_override(p_rid, RID());
+		instance_attach_skeleton(p_rid, RID());
+
+		if (instance->instance_allocated_shader_parameters) {
+			//free the used shader parameters
+			RSG::storage->global_variables_instance_free(instance->self);
+		}
+		update_dirty_instances(); //in case something changed this
+
+		instance_owner.free(p_rid);
+		memdelete(instance);
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
+TypedArray<Image> RenderingServerSceneRaster::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) {
+	return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);
+}
+
+/*******************************/
+/* Passthrough to Scene Render */
+/*******************************/
+
+/* ENVIRONMENT API */
+
+RenderingServerSceneRaster *RenderingServerSceneRaster::singleton = nullptr;
+
+RenderingServerSceneRaster::RenderingServerSceneRaster() {
+	render_pass = 1;
+	singleton = this;
+}
+
+RenderingServerSceneRaster::~RenderingServerSceneRaster() {
+}

+ 582 - 0
servers/rendering/rendering_server_scene_raster.h

@@ -0,0 +1,582 @@
+/*************************************************************************/
+/*  rendering_server_scene_raster.h                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef RENDERING_SERVER_SCENE_RASTER_H
+#define RENDERING_SERVER_SCENE_RASTER_H
+
+#include "core/templates/pass_func.h"
+#include "servers/rendering/rasterizer.h"
+
+#include "core/math/geometry_3d.h"
+#include "core/math/octree.h"
+#include "core/os/semaphore.h"
+#include "core/os/thread.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/rendering_server_scene.h"
+#include "servers/xr/xr_interface.h"
+
+class RenderingServerSceneRaster : public RenderingServerScene {
+public:
+	RasterizerScene *scene_render;
+
+	enum {
+		MAX_INSTANCE_CULL = 65536,
+		MAX_LIGHTS_CULLED = 4096,
+		MAX_REFLECTION_PROBES_CULLED = 4096,
+		MAX_DECALS_CULLED = 4096,
+		MAX_GI_PROBES_CULLED = 4096,
+		MAX_ROOM_CULL = 32,
+		MAX_LIGHTMAPS_CULLED = 4096,
+		MAX_EXTERIOR_PORTALS = 128,
+	};
+
+	uint64_t render_pass;
+
+	static RenderingServerSceneRaster *singleton;
+
+	/* CAMERA API */
+
+	struct Camera {
+		enum Type {
+			PERSPECTIVE,
+			ORTHOGONAL,
+			FRUSTUM
+		};
+		Type type;
+		float fov;
+		float znear, zfar;
+		float size;
+		Vector2 offset;
+		uint32_t visible_layers;
+		bool vaspect;
+		RID env;
+		RID effects;
+
+		Transform transform;
+
+		Camera() {
+			visible_layers = 0xFFFFFFFF;
+			fov = 75;
+			type = PERSPECTIVE;
+			znear = 0.05;
+			zfar = 100;
+			size = 1.0;
+			offset = Vector2();
+			vaspect = false;
+		}
+	};
+
+	mutable RID_PtrOwner<Camera> camera_owner;
+
+	virtual RID camera_create();
+	virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
+	virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
+	virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
+	virtual void camera_set_transform(RID p_camera, const Transform &p_transform);
+	virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers);
+	virtual void camera_set_environment(RID p_camera, RID p_env);
+	virtual void camera_set_camera_effects(RID p_camera, RID p_fx);
+	virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable);
+	virtual bool is_camera(RID p_camera) const;
+
+	/* SCENARIO API */
+
+	struct Instance;
+
+	struct Scenario {
+		RS::ScenarioDebugMode debug;
+		RID self;
+
+		Octree<Instance, true> octree;
+
+		List<Instance *> directional_lights;
+		RID environment;
+		RID fallback_environment;
+		RID camera_effects;
+		RID reflection_probe_shadow_atlas;
+		RID reflection_atlas;
+
+		SelfList<Instance>::List instances;
+
+		LocalVector<RID> dynamic_lights;
+
+		Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; }
+	};
+
+	mutable RID_PtrOwner<Scenario> scenario_owner;
+
+	static void *_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int);
+	static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *);
+
+	virtual RID scenario_create();
+
+	virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
+	virtual void scenario_set_environment(RID p_scenario, RID p_environment);
+	virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx);
+	virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
+	virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count);
+	virtual bool is_scenario(RID p_scenario) const;
+	virtual RID scenario_get_environment(RID p_scenario);
+
+	/* INSTANCING API */
+
+	struct InstanceBaseData {
+		virtual ~InstanceBaseData() {}
+	};
+
+	struct Instance : RasterizerScene::InstanceBase {
+		RID self;
+		//scenario stuff
+		OctreeElementID octree_id;
+		Scenario *scenario;
+		SelfList<Instance> scenario_item;
+
+		//aabb stuff
+		bool update_aabb;
+		bool update_dependencies;
+
+		SelfList<Instance> update_item;
+
+		AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better?
+		float extra_margin;
+		ObjectID object_id;
+
+		float lod_begin;
+		float lod_end;
+		float lod_begin_hysteresis;
+		float lod_end_hysteresis;
+		RID lod_instance;
+
+		Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior
+
+		uint64_t last_render_pass;
+		uint64_t last_frame_pass;
+
+		uint64_t version; // changes to this, and changes to base increase version
+
+		InstanceBaseData *base_data;
+
+		virtual void dependency_deleted(RID p_dependency) {
+			if (p_dependency == base) {
+				singleton->instance_set_base(self, RID());
+			} else if (p_dependency == skeleton) {
+				singleton->instance_attach_skeleton(self, RID());
+			} else {
+				singleton->_instance_queue_update(this, false, true);
+			}
+		}
+
+		virtual void dependency_changed(bool p_aabb, bool p_dependencies) {
+			singleton->_instance_queue_update(this, p_aabb, p_dependencies);
+		}
+
+		Instance() :
+				scenario_item(this),
+				update_item(this) {
+			octree_id = 0;
+			scenario = nullptr;
+
+			update_aabb = false;
+			update_dependencies = false;
+
+			extra_margin = 0;
+
+			visible = true;
+
+			lod_begin = 0;
+			lod_end = 0;
+			lod_begin_hysteresis = 0;
+			lod_end_hysteresis = 0;
+
+			last_render_pass = 0;
+			last_frame_pass = 0;
+			version = 1;
+			base_data = nullptr;
+
+			custom_aabb = nullptr;
+		}
+
+		~Instance() {
+			if (base_data) {
+				memdelete(base_data);
+			}
+			if (custom_aabb) {
+				memdelete(custom_aabb);
+			}
+		}
+	};
+
+	SelfList<Instance>::List _instance_update_list;
+	void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
+
+	struct InstanceGeometryData : public InstanceBaseData {
+		List<Instance *> lighting;
+		bool lighting_dirty;
+		bool can_cast_shadows;
+		bool material_is_animated;
+
+		List<Instance *> decals;
+		bool decal_dirty;
+
+		List<Instance *> reflection_probes;
+		bool reflection_dirty;
+
+		List<Instance *> gi_probes;
+		bool gi_probes_dirty;
+
+		List<Instance *> lightmap_captures;
+
+		InstanceGeometryData() {
+			lighting_dirty = false;
+			reflection_dirty = true;
+			can_cast_shadows = true;
+			material_is_animated = true;
+			gi_probes_dirty = true;
+			decal_dirty = true;
+		}
+	};
+
+	struct InstanceReflectionProbeData : public InstanceBaseData {
+		Instance *owner;
+
+		struct PairInfo {
+			List<Instance *>::Element *L; //reflection iterator in geometry
+			Instance *geometry;
+		};
+		List<PairInfo> geometries;
+
+		RID instance;
+		bool reflection_dirty;
+		SelfList<InstanceReflectionProbeData> update_list;
+
+		int render_step;
+
+		InstanceReflectionProbeData() :
+				update_list(this) {
+			reflection_dirty = true;
+			render_step = -1;
+		}
+	};
+
+	struct InstanceDecalData : public InstanceBaseData {
+		Instance *owner;
+		RID instance;
+
+		struct PairInfo {
+			List<Instance *>::Element *L; //reflection iterator in geometry
+			Instance *geometry;
+		};
+		List<PairInfo> geometries;
+
+		InstanceDecalData() {
+		}
+	};
+
+	SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
+
+	struct InstanceLightData : public InstanceBaseData {
+		struct PairInfo {
+			List<Instance *>::Element *L; //light iterator in geometry
+			Instance *geometry;
+		};
+
+		RID instance;
+		uint64_t last_version;
+		List<Instance *>::Element *D; // directional light in scenario
+
+		bool shadow_dirty;
+
+		List<PairInfo> geometries;
+
+		Instance *baked_light;
+
+		RS::LightBakeMode bake_mode;
+		uint32_t max_sdfgi_cascade = 2;
+
+		uint64_t sdfgi_cascade_light_pass = 0;
+
+		InstanceLightData() {
+			bake_mode = RS::LIGHT_BAKE_DISABLED;
+			shadow_dirty = true;
+			D = nullptr;
+			last_version = 0;
+			baked_light = nullptr;
+		}
+	};
+
+	struct InstanceGIProbeData : public InstanceBaseData {
+		Instance *owner;
+
+		struct PairInfo {
+			List<Instance *>::Element *L; //gi probe iterator in geometry
+			Instance *geometry;
+		};
+
+		List<PairInfo> geometries;
+		List<PairInfo> dynamic_geometries;
+
+		Set<Instance *> lights;
+
+		struct LightCache {
+			RS::LightType type;
+			Transform transform;
+			Color color;
+			float energy;
+			float bake_energy;
+			float radius;
+			float attenuation;
+			float spot_angle;
+			float spot_attenuation;
+			bool has_shadow;
+			bool sky_only;
+		};
+
+		Vector<LightCache> light_cache;
+		Vector<RID> light_instances;
+
+		RID probe_instance;
+
+		bool invalid;
+		uint32_t base_version;
+
+		SelfList<InstanceGIProbeData> update_element;
+
+		InstanceGIProbeData() :
+				update_element(this) {
+			invalid = true;
+			base_version = 0;
+		}
+	};
+
+	SelfList<InstanceGIProbeData>::List gi_probe_update_list;
+
+	struct InstanceLightmapData : public InstanceBaseData {
+		struct PairInfo {
+			List<Instance *>::Element *L; //iterator in geometry
+			Instance *geometry;
+		};
+		List<PairInfo> geometries;
+
+		Set<Instance *> users;
+
+		InstanceLightmapData() {
+		}
+	};
+
+	Set<Instance *> heightfield_particle_colliders_update_list;
+
+	int instance_cull_count;
+	Instance *instance_cull_result[MAX_INSTANCE_CULL];
+	Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
+	Instance *light_cull_result[MAX_LIGHTS_CULLED];
+	RID sdfgi_light_cull_result[MAX_LIGHTS_CULLED];
+	RID light_instance_cull_result[MAX_LIGHTS_CULLED];
+	uint64_t sdfgi_light_cull_pass = 0;
+	int light_cull_count;
+	int directional_light_count;
+	RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
+	RID decal_instance_cull_result[MAX_DECALS_CULLED];
+	int reflection_probe_cull_count;
+	int decal_cull_count;
+	RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
+	int gi_probe_cull_count;
+	Instance *lightmap_cull_result[MAX_LIGHTS_CULLED];
+	int lightmap_cull_count;
+
+	RID_PtrOwner<Instance> instance_owner;
+
+	virtual RID instance_create();
+
+	virtual void instance_set_base(RID p_instance, RID p_base);
+	virtual void instance_set_scenario(RID p_instance, RID p_scenario);
+	virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask);
+	virtual void instance_set_transform(RID p_instance, const Transform &p_transform);
+	virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id);
+	virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
+	virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material);
+	virtual void instance_set_visible(RID p_instance, bool p_visible);
+
+	virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
+
+	virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton);
+	virtual void instance_set_exterior(RID p_instance, bool p_enabled);
+
+	virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin);
+
+	// don't use these in a game!
+	virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const;
+	virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
+	virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const;
+
+	virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled);
+	virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting);
+	virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
+
+	virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
+	virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
+	virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
+
+	void _update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::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_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
+	virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const;
+	virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const;
+
+	_FORCE_INLINE_ void _update_instance(Instance *p_instance);
+	_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
+	_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
+	_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
+
+	_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario);
+
+	RID _render_get_environment(RID p_camera, RID p_scenario);
+
+	bool _render_reflection_probe_step(Instance *p_instance, int p_step);
+	void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
+	void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+	void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
+
+	void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
+	void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
+	void update_dirty_instances();
+
+	void render_particle_colliders();
+	virtual void render_probes();
+
+	TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size);
+
+	//pass to scene render
+
+	/* ENVIRONMENT API */
+
+#ifdef PASSBASE
+#undef PASSBASE
+#endif
+
+#define PASSBASE scene_render
+
+	PASS1(directional_shadow_atlas_set_size, int)
+	PASS1(gi_probe_set_quality, RS::GIProbeQuality)
+
+	/* SKY API */
+
+	PASS0R(RID, sky_create)
+	PASS2(sky_set_radiance_size, RID, int)
+	PASS2(sky_set_mode, RID, RS::SkyMode)
+	PASS2(sky_set_material, RID, RID)
+	PASS4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &)
+
+	PASS0R(RID, environment_create)
+
+	PASS1RC(bool, is_environment, RID)
+
+	PASS2(environment_set_background, RID, RS::EnvironmentBG)
+	PASS2(environment_set_sky, RID, RID)
+	PASS2(environment_set_sky_custom_fov, RID, float)
+	PASS2(environment_set_sky_orientation, RID, const Basis &)
+	PASS2(environment_set_bg_color, RID, const Color &)
+	PASS2(environment_set_bg_energy, RID, float)
+	PASS2(environment_set_canvas_max_layer, RID, int)
+	PASS7(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource, const Color &)
+
+	PASS6(environment_set_ssr, RID, bool, int, float, float, float)
+	PASS1(environment_set_ssr_roughness_quality, RS::EnvironmentSSRRoughnessQuality)
+
+	PASS9(environment_set_ssao, RID, bool, float, float, float, float, float, RS::EnvironmentSSAOBlur, float)
+	PASS2(environment_set_ssao_quality, RS::EnvironmentSSAOQuality, bool)
+
+	PASS11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float)
+	PASS1(environment_glow_set_use_bicubic_upscale, bool)
+	PASS1(environment_glow_set_use_high_quality, bool)
+
+	PASS9(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float, bool, float, float, float, float)
+
+	PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
+
+	PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
+	PASS9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, RS::EnvVolumetricFogShadowFilter)
+
+	PASS2(environment_set_volumetric_fog_volume_size, int, int)
+	PASS1(environment_set_volumetric_fog_filter_active, bool)
+	PASS1(environment_set_volumetric_fog_directional_shadow_shrink_size, int)
+	PASS1(environment_set_volumetric_fog_positional_shadow_shrink_size, int)
+
+	PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
+	PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount)
+	PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge)
+
+	PASS1RC(RS::EnvironmentBG, environment_get_background, RID)
+	PASS1RC(int, environment_get_canvas_max_layer, RID)
+
+	PASS3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
+
+	PASS3(screen_space_roughness_limiter_set_active, bool, float, float)
+	PASS1(sub_surface_scattering_set_quality, RS::SubSurfaceScatteringQuality)
+	PASS2(sub_surface_scattering_set_scale, float, float)
+
+	/* CAMERA EFFECTS */
+
+	PASS0R(RID, camera_effects_create)
+
+	PASS2(camera_effects_set_dof_blur_quality, RS::DOFBlurQuality, bool)
+	PASS1(camera_effects_set_dof_blur_bokeh_shape, RS::DOFBokehShape)
+
+	PASS8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
+	PASS3(camera_effects_set_custom_exposure, RID, bool, float)
+
+	PASS1(shadows_quality_set, RS::ShadowQuality)
+	PASS1(directional_shadow_quality_set, RS::ShadowQuality)
+
+	PASS2(sdfgi_set_debug_probe_select, const Vector3 &, const Vector3 &)
+
+	/* Render Buffers */
+
+	PASS0R(RID, render_buffers_create)
+	PASS7(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool)
+
+	/* Shadow Atlas */
+	PASS0R(RID, shadow_atlas_create)
+	PASS2(shadow_atlas_set_size, RID, int)
+	PASS3(shadow_atlas_set_quadrant_subdivision, RID, int, int)
+
+	PASS1(set_debug_draw_mode, RS::ViewportDebugDraw)
+
+	virtual void update();
+
+	bool free(RID p_rid);
+
+	RenderingServerSceneRaster();
+	virtual ~RenderingServerSceneRaster();
+};
+
+#endif // VISUALSERVERSCENE_H

+ 21 - 23
servers/rendering/rendering_server_viewport.cpp

@@ -33,7 +33,7 @@
 #include "core/config/project_settings.h"
 #include "rendering_server_canvas.h"
 #include "rendering_server_globals.h"
-#include "rendering_server_scene.h"
+#include "rendering_server_scene_raster.h"
 
 static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_viewport, RenderingServerCanvas::Canvas *p_canvas, RenderingServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
 	Transform2D xf = p_viewport->global_transform;
@@ -101,17 +101,15 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
 
 	Color bgcolor = RSG::storage->get_default_clear_color();
 
-	if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->scenario_owner.owns(p_viewport->scenario)) {
-		RenderingServerScene::Scenario *scenario = RSG::scene->scenario_owner.getornull(p_viewport->scenario);
-		ERR_FAIL_COND(!scenario);
-		if (RSG::scene_render->is_environment(scenario->environment)) {
-			scenario_draw_canvas_bg = RSG::scene_render->environment_get_background(scenario->environment) == RS::ENV_BG_CANVAS;
-
-			scenario_canvas_max_layer = RSG::scene_render->environment_get_canvas_max_layer(scenario->environment);
+	if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) {
+		RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario);
+		if (RSG::scene->is_environment(environment)) {
+			scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS;
+			scenario_canvas_max_layer = RSG::scene->environment_get_canvas_max_layer(environment);
 		}
 	}
 
-	bool can_draw_3d = RSG::scene->camera_owner.owns(p_viewport->camera);
+	bool can_draw_3d = RSG::scene->is_camera(p_viewport->camera);
 
 	if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
 		if (p_viewport->transparent_bg) {
@@ -124,8 +122,8 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::
 
 	if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
 		//wants to draw 3D but there is no render buffer, create
-		p_viewport->render_buffers = RSG::scene_render->render_buffers_create();
-		RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding);
+		p_viewport->render_buffers = RSG::scene->render_buffers_create();
+		RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding);
 	}
 
 	RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
@@ -559,7 +557,7 @@ void RenderingServerViewport::draw_viewports() {
 		{
 			RSG::storage->render_target_set_external_texture(vp->render_target, 0);
 
-			RSG::scene_render->set_debug_draw_mode(vp->debug_draw);
+			RSG::scene->set_debug_draw_mode(vp->debug_draw);
 			RSG::storage->render_info_begin_capture();
 
 			// render standard mono camera
@@ -598,7 +596,7 @@ void RenderingServerViewport::draw_viewports() {
 
 		RENDER_TIMESTAMP("<Rendering Viewport " + itos(i));
 	}
-	RSG::scene_render->set_debug_draw_mode(RS::VIEWPORT_DEBUG_DRAW_DISABLED);
+	RSG::scene->set_debug_draw_mode(RS::VIEWPORT_DEBUG_DRAW_DISABLED);
 
 	RENDER_TIMESTAMP("<Render Viewports");
 	//this needs to be called to make screen swapping more efficient
@@ -618,7 +616,7 @@ RID RenderingServerViewport::viewport_create() {
 	viewport->hide_scenario = false;
 	viewport->hide_canvas = false;
 	viewport->render_target = RSG::storage->render_target_create();
-	viewport->shadow_atlas = RSG::scene_render->shadow_atlas_create();
+	viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
 	viewport->viewport_render_direct_to_screen = false;
 
 	return rid;
@@ -641,10 +639,10 @@ void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int
 	RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height);
 	if (viewport->render_buffers.is_valid()) {
 		if (p_width == 0 || p_height == 0) {
-			RSG::scene_render->free(viewport->render_buffers);
+			RSG::scene->free(viewport->render_buffers);
 			viewport->render_buffers = RID();
 		} else {
-			RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding);
+			RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding);
 		}
 	}
 }
@@ -838,14 +836,14 @@ void RenderingServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int
 
 	viewport->shadow_atlas_size = p_size;
 
-	RSG::scene_render->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size);
+	RSG::scene->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size);
 }
 
 void RenderingServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
 	Viewport *viewport = viewport_owner.getornull(p_viewport);
 	ERR_FAIL_COND(!viewport);
 
-	RSG::scene_render->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv);
+	RSG::scene->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv);
 }
 
 void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) {
@@ -857,7 +855,7 @@ void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA
 	}
 	viewport->msaa = p_msaa;
 	if (viewport->render_buffers.is_valid()) {
-		RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding);
+		RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding);
 	}
 }
 
@@ -870,7 +868,7 @@ void RenderingServerViewport::viewport_set_screen_space_aa(RID p_viewport, RS::V
 	}
 	viewport->screen_space_aa = p_mode;
 	if (viewport->render_buffers.is_valid()) {
-		RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding);
+		RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding);
 	}
 }
 
@@ -883,7 +881,7 @@ void RenderingServerViewport::viewport_set_use_debanding(RID p_viewport, bool p_
 	}
 	viewport->use_debanding = p_use_debanding;
 	if (viewport->render_buffers.is_valid()) {
-		RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding);
+		RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding);
 	}
 }
 
@@ -965,9 +963,9 @@ bool RenderingServerViewport::free(RID p_rid) {
 		Viewport *viewport = viewport_owner.getornull(p_rid);
 
 		RSG::storage->free(viewport->render_target);
-		RSG::scene_render->free(viewport->shadow_atlas);
+		RSG::scene->free(viewport->shadow_atlas);
 		if (viewport->render_buffers.is_valid()) {
-			RSG::scene_render->free(viewport->render_buffers);
+			RSG::scene->free(viewport->render_buffers);
 		}
 
 		while (viewport->canvas_map.front()) {