Преглед изворни кода

Rewrote large part of rendering, omni and spot shadows now work.

Juan Linietsky пре 6 година
родитељ
комит
920db604d2
35 измењених фајлова са 3604 додато и 740 уклоњено
  1. 22 0
      core/math/camera_matrix.cpp
  2. 1 0
      core/math/camera_matrix.h
  3. 7 8
      drivers/gles3/rasterizer_scene_gles3.h
  4. 150 21
      drivers/vulkan/rendering_device_vulkan.cpp
  5. 2 0
      drivers/vulkan/rendering_device_vulkan.h
  6. 6 0
      main/main.cpp
  7. 0 18
      scene/3d/light.cpp
  8. 0 11
      scene/3d/light.h
  9. 0 4
      scene/main/scene_tree.cpp
  10. 2 0
      servers/visual/rasterizer.cpp
  11. 3 28
      servers/visual/rasterizer.h
  12. 1 1
      servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp
  13. 48 1
      servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
  14. 25 2
      servers/visual/rasterizer_rd/rasterizer_effects_rd.h
  15. 511 186
      servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
  16. 100 49
      servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
  17. 982 156
      servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
  18. 329 29
      servers/visual/rasterizer_rd/rasterizer_scene_rd.h
  19. 490 30
      servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
  20. 191 54
      servers/visual/rasterizer_rd/rasterizer_storage_rd.h
  21. 12 2
      servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
  22. 1 0
      servers/visual/rasterizer_rd/shaders/SCsub
  23. 4 0
      servers/visual/rasterizer_rd/shaders/blur.glsl
  24. 1 0
      servers/visual/rasterizer_rd/shaders/blur_inc.glsl
  25. 93 0
      servers/visual/rasterizer_rd/shaders/copy.glsl
  26. 491 12
      servers/visual/rasterizer_rd/shaders/scene_forward.glsl
  27. 110 48
      servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
  28. 3 7
      servers/visual/rasterizer_rd/shaders/tonemap.glsl
  29. 2 2
      servers/visual/visual_server_raster.cpp
  30. 2 2
      servers/visual/visual_server_raster.h
  31. 8 51
      servers/visual/visual_server_scene.cpp
  32. 0 2
      servers/visual/visual_server_scene.h
  33. 2 2
      servers/visual/visual_server_wrap_mt.h
  34. 0 4
      servers/visual_server.cpp
  35. 5 10
      servers/visual_server.h

+ 22 - 0
core/math/camera_matrix.cpp

@@ -512,6 +512,28 @@ CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const {
 	return new_matrix;
 }
 
+void CameraMatrix::set_depth_correction() {
+
+	real_t *m = &matrix[0][0];
+
+	m[0] = 1;
+	m[1] = 0.0;
+	m[2] = 0.0;
+	m[3] = 0.0;
+	m[4] = 0.0;
+	m[5] = -1;
+	m[6] = 0.0;
+	m[7] = 0.0;
+	m[8] = 0.0;
+	m[9] = 0.0;
+	m[10] = 0.5;
+	m[11] = 0.0;
+	m[12] = 0.0;
+	m[13] = 0.0;
+	m[14] = 0.5;
+	m[15] = 1.0;
+}
+
 void CameraMatrix::set_light_bias() {
 
 	real_t *m = &matrix[0][0];

+ 1 - 0
core/math/camera_matrix.h

@@ -50,6 +50,7 @@ struct CameraMatrix {
 	void set_identity();
 	void set_zero();
 	void set_light_bias();
+	void set_depth_correction();
 	void set_light_atlas_rect(const Rect2 &p_rect);
 	void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
 	void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov, int p_eye, real_t p_intraocular_dist, real_t p_convergence_dist);

+ 7 - 8
drivers/gles3/rasterizer_scene_gles3.h

@@ -216,7 +216,7 @@ public:
 
 	/* SHADOW ATLAS API */
 
-	struct ShadowAtlas  {
+	struct ShadowAtlas {
 
 		enum {
 			QUADRANT_SHIFT = 27,
@@ -288,7 +288,7 @@ public:
 
 	/* REFLECTION PROBE ATLAS API */
 
-	struct ReflectionAtlas  {
+	struct ReflectionAtlas {
 
 		int subdiv;
 		int size;
@@ -307,8 +307,7 @@ public:
 	mutable RID_PtrOwner<ReflectionAtlas> reflection_atlas_owner;
 
 	virtual RID reflection_atlas_create();
-	virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size);
-	virtual void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv);
+	virtual void reflection_atlas_configure(RID p_ref_atlas, int p_size, int p_count);
 
 	/* REFLECTION CUBEMAPS */
 
@@ -324,7 +323,7 @@ public:
 
 	/* REFLECTION PROBE INSTANCE */
 
-	struct ReflectionProbeInstance  {
+	struct ReflectionProbeInstance {
 
 		RasterizerStorageGLES3::ReflectionProbe *probe_ptr;
 		RID probe;
@@ -364,7 +363,7 @@ public:
 
 	/* ENVIRONMENT API */
 
-	struct Environment  {
+	struct Environment {
 
 		VS::EnvironmentBG bg_mode;
 
@@ -590,7 +589,7 @@ public:
 		float shadow_split_offsets[4];
 	};
 
-	struct LightInstance  {
+	struct LightInstance {
 
 		struct ShadowTransform {
 
@@ -639,7 +638,7 @@ public:
 
 	/* REFLECTION INSTANCE */
 
-	struct GIProbeInstance  {
+	struct GIProbeInstance {
 		RID data;
 		RasterizerStorageGLES3::GIProbe *probe;
 		GLuint tex_cache;

+ 150 - 21
drivers/vulkan/rendering_device_vulkan.cpp

@@ -1497,6 +1497,23 @@ void RenderingDeviceVulkan::_memory_barrier(VkPipelineStageFlags p_src_stage_mas
 
 	vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 1, &mem_barrier, 0, NULL, 0, NULL);
 }
+
+void RenderingDeviceVulkan::_buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw) {
+
+	VkBufferMemoryBarrier buffer_mem_barrier;
+	buffer_mem_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+	buffer_mem_barrier.pNext = NULL;
+	buffer_mem_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+	buffer_mem_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+	buffer_mem_barrier.srcAccessMask = p_src_access;
+	buffer_mem_barrier.dstAccessMask = p_dst_sccess;
+	buffer_mem_barrier.buffer = buffer;
+	buffer_mem_barrier.offset = p_from;
+	buffer_mem_barrier.size = p_size;
+
+	vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, p_src_stage_mask, p_dst_stage_mask, 0, 0, NULL, 1, &buffer_mem_barrier, 0, NULL);
+}
+
 /*****************/
 /**** TEXTURE ****/
 /*****************/
@@ -1715,7 +1732,7 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
 		}
 
 		if (p_format.usage_bits & TEXTURE_USAGE_SAMPLING_BIT) {
-			texture.unbound_layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
+			texture.unbound_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 		} else {
 			texture.unbound_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 		}
@@ -2526,6 +2543,9 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
 	ERR_FAIL_COND_V(p_dst_mipmap >= dst_tex->mipmaps, ERR_INVALID_PARAMETER);
 	ERR_FAIL_COND_V(p_dst_layer >= dst_layer_count, ERR_INVALID_PARAMETER);
 
+	ERR_FAIL_COND_V_MSG(src_tex->read_aspect_mask != dst_tex->read_aspect_mask, ERR_INVALID_PARAMETER,
+			"Source and destination texture must be of the same type (color or depth).");
+
 	VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
 
 	{
@@ -2586,7 +2606,7 @@ Error RenderingDeviceVulkan::texture_copy(RID p_from_texture, RID p_to_texture,
 			image_copy_region.srcOffset.y = p_from.y;
 			image_copy_region.srcOffset.z = p_from.z;
 
-			image_copy_region.dstSubresource.aspectMask = src_tex->barrier_aspect_mask;
+			image_copy_region.dstSubresource.aspectMask = dst_tex->read_aspect_mask;
 			image_copy_region.dstSubresource.baseArrayLayer = p_dst_layer;
 			image_copy_region.dstSubresource.layerCount = 1;
 			image_copy_region.dstSubresource.mipLevel = p_dst_mipmap;
@@ -2712,6 +2732,8 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
 		ERR_FAIL_COND_V_MSG(!(p_format[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT)), VK_NULL_HANDLE,
 				"Texture format for index (" + itos(i) + ") requires an attachment (depth, stencil or resolve) bit set.");
 
+		bool can_be_sampled = p_format[i].usage_flags & TEXTURE_USAGE_SAMPLING_BIT;
+
 		switch (p_initial_action) {
 
 			case INITIAL_ACTION_CLEAR: {
@@ -2722,7 +2744,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
 			case INITIAL_ACTION_KEEP_COLOR: {
 				if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
 					description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
-					description.initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+					description.initialLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 					description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 				} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
 					description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
@@ -2738,10 +2760,10 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
 
 				if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
 					description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
-					description.initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+					description.initialLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 				} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
 					description.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
-					description.initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL; //don't care what is there
+					description.initialLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; //don't care what is there
 					description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
 				} else {
 					description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -2772,15 +2794,16 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
 
 		switch (p_final_action) {
 			case FINAL_ACTION_READ_COLOR_AND_DEPTH: {
+
 				if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
 					description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 					description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-					description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+					description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 				} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
 
 					description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 					description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
-					description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
+					description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 				} else {
 					description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 					description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -2791,12 +2814,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
 					if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
 						description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 						description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-						description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+						description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 					} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
 
 						description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 						description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-						description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
+						description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 					} else {
 						description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 						description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -2807,12 +2830,12 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
 					if (p_format[i].usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
 						description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 						description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-						description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+						description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 					} else if (p_format[i].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
 
 						description.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
 						description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-						description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
+						description.finalLayout = can_be_sampled ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
 					} else {
 						description.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 						description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
@@ -3062,7 +3085,7 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Poo
 		uint64_t data_size = p_data.size();
 		PoolVector<uint8_t>::Read r = p_data.read();
 		_buffer_update(&buffer, 0, r.ptr(), data_size);
-		_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false);
+		_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false);
 	}
 
 	return vertex_buffer_owner.make_rid(buffer);
@@ -3223,7 +3246,7 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff
 		uint64_t data_size = p_data.size();
 		PoolVector<uint8_t>::Read r = p_data.read();
 		_buffer_update(&index_buffer, 0, r.ptr(), data_size);
-		_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false);
+		_buffer_memory_barrier(index_buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false);
 	}
 	return index_buffer_owner.make_rid(index_buffer);
 }
@@ -3934,7 +3957,7 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Po
 		uint64_t data_size = p_data.size();
 		PoolVector<uint8_t>::Read r = p_data.read();
 		_buffer_update(&buffer, 0, r.ptr(), data_size);
-		_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false);
+		_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false);
 	}
 	return uniform_buffer_owner.make_rid(buffer);
 }
@@ -3953,7 +3976,7 @@ RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Po
 		uint64_t data_size = p_data.size();
 		PoolVector<uint8_t>::Read r = p_data.read();
 		_buffer_update(&buffer, 0, r.ptr(), data_size);
-		_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, false);
+		_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, false);
 	}
 	return storage_buffer_owner.make_rid(buffer);
 }
@@ -3976,7 +3999,7 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF
 		uint64_t data_size = p_data.size();
 		PoolVector<uint8_t>::Read r = p_data.read();
 		_buffer_update(&texture_buffer.buffer, 0, r.ptr(), data_size);
-		_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, false);
+		_buffer_memory_barrier(texture_buffer.buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, false);
 	}
 
 	VkBufferViewCreateInfo view_create_info;
@@ -4400,7 +4423,8 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 				Buffer *buffer = storage_buffer_owner.getornull(uniform.ids[0]);
 				ERR_FAIL_COND_V_MSG(!buffer, RID(), "Storage buffer supplied (binding: " + itos(uniform.binding) + ") is invalid.");
 
-				ERR_FAIL_COND_V_MSG(buffer->size != (uint32_t)set_uniform.length, RID(),
+				//if 0, then its sized on link time
+				ERR_FAIL_COND_V_MSG(set_uniform.length > 0 && buffer->size != (uint32_t)set_uniform.length, RID(),
 						"Storage buffer supplied (binding: " + itos(uniform.binding) + ") size (" + itos(buffer->size) + " does not match size of shader uniform: (" + itos(set_uniform.length) + ").");
 
 				write.dstArrayElement = 0;
@@ -4523,8 +4547,47 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
 		return err;
 	}
 
-	_memory_barrier(VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_sync_with_draw);
-
+	_buffer_memory_barrier(buffer->buffer, p_offset, p_size, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_stage_mask, VK_ACCESS_TRANSFER_WRITE_BIT, dst_access, p_sync_with_draw);
+#if 0
+	if (p_sync_with_draw) {
+		VkMemoryBarrier memoryBarrier;
+
+		memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
+		memoryBarrier.pNext = NULL;
+		memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
+									  VK_ACCESS_INDEX_READ_BIT |
+									  VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
+									  VK_ACCESS_UNIFORM_READ_BIT |
+									  VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
+									  VK_ACCESS_SHADER_READ_BIT |
+									  VK_ACCESS_SHADER_WRITE_BIT |
+									  VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+									  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
+									  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+									  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
+									  VK_ACCESS_TRANSFER_READ_BIT |
+									  VK_ACCESS_TRANSFER_WRITE_BIT |
+									  VK_ACCESS_HOST_READ_BIT |
+									  VK_ACCESS_HOST_WRITE_BIT;
+		memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
+									  VK_ACCESS_INDEX_READ_BIT |
+									  VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
+									  VK_ACCESS_UNIFORM_READ_BIT |
+									  VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
+									  VK_ACCESS_SHADER_READ_BIT |
+									  VK_ACCESS_SHADER_WRITE_BIT |
+									  VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
+									  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
+									  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+									  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
+									  VK_ACCESS_TRANSFER_READ_BIT |
+									  VK_ACCESS_TRANSFER_WRITE_BIT |
+									  VK_ACCESS_HOST_READ_BIT |
+									  VK_ACCESS_HOST_WRITE_BIT;
+
+		vkCmdPipelineBarrier(p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &memoryBarrier, 0, NULL, 0, NULL);
+	}
+#endif
 	return err;
 }
 
@@ -5145,6 +5208,47 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
 	return OK;
 }
 
+void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, const Vector<Color> &p_clear_colors) {
+	Vector<VkClearAttachment> clear_attachments;
+	int color_index = 0;
+	for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
+		Texture *texture = texture_owner.getornull(framebuffer->texture_ids[i]);
+		VkClearAttachment clear_at;
+		if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+			ERR_FAIL_INDEX(color_index, p_clear_colors.size()); //a bug
+			Color clear_color = p_clear_colors[color_index];
+			clear_at.clearValue.color.float32[0] = clear_color.r;
+			clear_at.clearValue.color.float32[1] = clear_color.g;
+			clear_at.clearValue.color.float32[2] = clear_color.b;
+			clear_at.clearValue.color.float32[3] = clear_color.a;
+			clear_at.colorAttachment = color_index++;
+			clear_at.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+		} else if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+
+			clear_at.clearValue.depthStencil.depth = 1.0;
+			clear_at.clearValue.depthStencil.stencil = 0;
+			clear_at.colorAttachment = 0;
+			clear_at.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+			if (format_has_stencil(texture->format)) {
+				clear_at.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+			}
+		} else {
+			ERR_CONTINUE(true);
+		}
+		clear_attachments.push_back(clear_at);
+	}
+
+	VkClearRect cr;
+	cr.baseArrayLayer = 0;
+	cr.layerCount = 1;
+	cr.rect.offset.x = viewport_offset.x;
+	cr.rect.offset.y = viewport_offset.y;
+	cr.rect.extent.width = viewport_size.width;
+	cr.rect.extent.height = viewport_size.height;
+
+	vkCmdClearAttachments(draw_list->command_buffer, clear_attachments.size(), clear_attachments.ptr(), 1, &cr);
+}
+
 RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_colors, const Rect2 &p_region) {
 
 	_THREAD_SAFE_METHOD_
@@ -5154,8 +5258,9 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
 
 	Point2i viewport_offset;
 	Point2i viewport_size = framebuffer->size;
+	bool needs_clear_region = false;
 
-	if (p_region != Rect2()) { //check custom region
+	if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region
 		Rect2i viewport(viewport_offset, viewport_size);
 		Rect2i regioni = p_region;
 		if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
@@ -5166,6 +5271,11 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
 
 		viewport_offset = regioni.position;
 		viewport_size = regioni.size;
+
+		if (p_initial_action == INITIAL_ACTION_CLEAR) {
+			p_initial_action = INITIAL_ACTION_KEEP_COLOR_AND_DEPTH;
+			needs_clear_region = true;
+		}
 	}
 
 	if (p_initial_action == INITIAL_ACTION_CLEAR) { //check clear values
@@ -5196,6 +5306,10 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
 	draw_list_count = 0;
 	draw_list_split = false;
 
+	if (needs_clear_region) {
+		_draw_list_insert_clear_region(draw_list, framebuffer, viewport_offset, viewport_size, p_clear_colors);
+	}
+
 	VkViewport viewport;
 	viewport.x = viewport_offset.x;
 	viewport.y = viewport_offset.y;
@@ -5230,7 +5344,9 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
 	Point2i viewport_offset;
 	Point2i viewport_size = framebuffer->size;
 
-	if (p_region != Rect2()) { //check custom region
+	bool needs_clear_region = false;
+
+	if (p_region != Rect2() && p_region != Rect2(Vector2(), viewport_size)) { //check custom region
 		Rect2i viewport(viewport_offset, viewport_size);
 		Rect2i regioni = p_region;
 		if (!(regioni.position.x >= viewport.position.x) && (regioni.position.y >= viewport.position.y) &&
@@ -5241,6 +5357,11 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
 
 		viewport_offset = regioni.position;
 		viewport_size = regioni.size;
+
+		if (p_initial_action == INITIAL_ACTION_CLEAR) {
+			p_initial_action = INITIAL_ACTION_KEEP_COLOR_AND_DEPTH;
+			needs_clear_region = true;
+		}
 	}
 
 	if (p_initial_action == INITIAL_ACTION_CLEAR) { //check clear values
@@ -5340,6 +5461,9 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
 #ifdef DEBUG_ENABLED
 		draw_list[i].validation.framebuffer_format = framebuffer->format_id;
 #endif
+		if (i == 0 && needs_clear_region) {
+			_draw_list_insert_clear_region(&draw_list[i], framebuffer, viewport_offset, viewport_size, p_clear_colors);
+		}
 
 		VkViewport viewport;
 		viewport.x = viewport_offset.x;
@@ -5754,6 +5878,11 @@ void RenderingDeviceVulkan::draw_list_end() {
 		}
 	}
 	draw_list_bound_textures.clear();
+
+	// To ensure proper synchronization, we must make sure rendering is done before:
+	//  * Some buffer is copied
+	//  * Another render pass happens (since we may be done
+	_memory_barrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT, true);
 }
 #if 0
 void RenderingDeviceVulkan::draw_list_render_secondary_to_framebuffer(ID p_framebuffer, ID *p_draw_lists, uint32_t p_draw_list_count, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Variant> &p_clear_colors) {

+ 2 - 0
drivers/vulkan/rendering_device_vulkan.h

@@ -216,6 +216,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
 	Error _buffer_update(Buffer *p_buffer, size_t p_offset, const uint8_t *p_data, size_t p_data_size, bool p_use_draw_command_buffer = false, uint32_t p_required_align = 32);
 
 	void _memory_barrier(VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw);
+	void _buffer_memory_barrier(VkBuffer buffer, uint64_t p_from, uint64_t p_size, VkPipelineStageFlags p_src_stage_mask, VkPipelineStageFlags p_dst_stage_mask, VkAccessFlags p_src_access, VkAccessFlags p_dst_sccess, bool p_sync_with_draw);
 
 	/*********************/
 	/**** FRAMEBUFFER ****/
@@ -790,6 +791,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
 	Vector<RID> draw_list_bound_textures;
 	bool draw_list_unbind_textures;
 
+	void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, const Vector<Color> &p_clear_colors);
 	Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_action, FinalAction p_final_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass);
 	Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Color> &p_clear_colors, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents);
 	_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);

+ 6 - 0
main/main.cpp

@@ -1753,6 +1753,12 @@ bool Main::start() {
 		}
 #endif
 
+		{
+
+			int directional_atlas_size = GLOBAL_GET("rendering/quality/directional_shadow/size");
+			VisualServer::get_singleton()->directional_shadow_atlas_set_size(directional_atlas_size);
+		}
+
 		if (!editor && !project_manager) {
 			//standard helpers that can be changed from main config
 

+ 0 - 18
scene/3d/light.cpp

@@ -431,42 +431,24 @@ OmniLight::ShadowMode OmniLight::get_shadow_mode() const {
 	return shadow_mode;
 }
 
-void OmniLight::set_shadow_detail(ShadowDetail p_detail) {
-
-	shadow_detail = p_detail;
-	VS::get_singleton()->light_omni_set_shadow_detail(light, VS::LightOmniShadowDetail(p_detail));
-}
-OmniLight::ShadowDetail OmniLight::get_shadow_detail() const {
-
-	return shadow_detail;
-}
-
 void OmniLight::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &OmniLight::set_shadow_mode);
 	ClassDB::bind_method(D_METHOD("get_shadow_mode"), &OmniLight::get_shadow_mode);
 
-	ClassDB::bind_method(D_METHOD("set_shadow_detail", "detail"), &OmniLight::set_shadow_detail);
-	ClassDB::bind_method(D_METHOD("get_shadow_detail"), &OmniLight::get_shadow_detail);
-
 	ADD_GROUP("Omni", "omni_");
 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_range", PROPERTY_HINT_EXP_RANGE, "0,4096,0.1,or_greater"), "set_param", "get_param", PARAM_RANGE);
 	ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_ATTENUATION);
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_detail", PROPERTY_HINT_ENUM, "Vertical,Horizontal"), "set_shadow_detail", "get_shadow_detail");
 
 	BIND_ENUM_CONSTANT(SHADOW_DUAL_PARABOLOID);
 	BIND_ENUM_CONSTANT(SHADOW_CUBE);
-
-	BIND_ENUM_CONSTANT(SHADOW_DETAIL_VERTICAL);
-	BIND_ENUM_CONSTANT(SHADOW_DETAIL_HORIZONTAL);
 }
 
 OmniLight::OmniLight() :
 		Light(VisualServer::LIGHT_OMNI) {
 
 	set_shadow_mode(SHADOW_CUBE);
-	set_shadow_detail(SHADOW_DETAIL_HORIZONTAL);
 }
 
 String SpotLight::get_configuration_warning() const {

+ 0 - 11
scene/3d/light.h

@@ -183,15 +183,8 @@ public:
 		SHADOW_CUBE,
 	};
 
-	// omni light
-	enum ShadowDetail {
-		SHADOW_DETAIL_VERTICAL,
-		SHADOW_DETAIL_HORIZONTAL
-	};
-
 private:
 	ShadowMode shadow_mode;
-	ShadowDetail shadow_detail;
 
 protected:
 	static void _bind_methods();
@@ -200,14 +193,10 @@ public:
 	void set_shadow_mode(ShadowMode p_mode);
 	ShadowMode get_shadow_mode() const;
 
-	void set_shadow_detail(ShadowDetail p_detail);
-	ShadowDetail get_shadow_detail() const;
-
 	OmniLight();
 };
 
 VARIANT_ENUM_CAST(OmniLight::ShadowMode)
-VARIANT_ENUM_CAST(OmniLight::ShadowDetail)
 
 class SpotLight : public Light {
 

+ 0 - 4
scene/main/scene_tree.cpp

@@ -2075,14 +2075,10 @@ SceneTree::SceneTree() {
 
 	int ref_atlas_size = GLOBAL_DEF("rendering/quality/reflections/atlas_size", 2048);
 	ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_size", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_size", PROPERTY_HINT_RANGE, "0,8192,or_greater")); //next_power_of_2 will return a 0 as min value
-	int ref_atlas_subdiv = GLOBAL_DEF("rendering/quality/reflections/atlas_subdiv", 8);
-	ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_subdiv", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_subdiv", PROPERTY_HINT_RANGE, "0,32,or_greater")); //next_power_of_2 will return a 0 as min value
 	int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0);
 	ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"));
 	root->set_msaa(Viewport::MSAA(msaa_mode));
 
-	VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(), ref_atlas_size, ref_atlas_subdiv);
-
 	{ //load default fallback environment
 		//get possible extensions
 		List<String> exts;

+ 2 - 0
servers/visual/rasterizer.cpp

@@ -47,6 +47,8 @@ void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted)
 	for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
 		E->key()->dependencies.erase(this);
 	}
+
+	instances.clear();
 }
 
 RasterizerScene::InstanceDependency::~InstanceDependency() {

+ 3 - 28
servers/visual/rasterizer.h

@@ -46,6 +46,7 @@ public:
 	virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
 	virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
 
+	virtual void directional_shadow_atlas_set_size(int p_size) = 0;
 	virtual int get_directional_light_shadow_size(RID p_light_intance) = 0;
 	virtual void set_directional_shadow_count(int p_count) = 0;
 
@@ -107,18 +108,11 @@ public:
 		Map<InstanceBase *, uint32_t> instances;
 	};
 
-	struct InstanceCustomData {
-
-		virtual ~InstanceCustomData() {}
-	};
-
 	struct InstanceBase {
 
 		VS::InstanceType base_type;
 		RID base;
 
-		InstanceCustomData *custom_data;
-
 		RID skeleton;
 		RID material_override;
 
@@ -201,7 +195,6 @@ public:
 		InstanceBase() :
 				dependency_item(this) {
 
-			custom_data = nullptr;
 			base_type = VS::INSTANCE_NONE;
 			cast_shadows = VS::SHADOW_CASTING_SETTING_ON;
 			receive_shadows = true;
@@ -215,9 +208,6 @@ public:
 		}
 
 		virtual ~InstanceBase() {
-			if (custom_data) {
-				memdelete(custom_data);
-			}
 			clear_dependencies();
 		}
 	};
@@ -228,16 +218,10 @@ public:
 	virtual void light_instance_mark_visible(RID p_light_instance) = 0;
 	virtual bool light_instances_can_render_shadow_cube() const { return true; }
 
-	virtual RID reflection_atlas_create() = 0;
-	virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size) = 0;
-	virtual void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) = 0;
-
 	virtual RID reflection_probe_instance_create(RID p_probe) = 0;
 	virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
-	virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
 	virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
-	virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
-	virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
+	virtual void reflection_probe_instance_begin_render(RID p_instance) = 0;
 	virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
 
 	virtual RID gi_probe_instance_create() = 0;
@@ -245,21 +229,13 @@ public:
 	virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
 	virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) = 0;
 
-	virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+	virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
 	virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
 
 	virtual void set_scene_pass(uint64_t p_pass) = 0;
 	virtual void set_time(double p_time) = 0;
 	virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) = 0;
 
-	virtual void instance_create_custom_data(InstanceBase *p_instance) = 0;
-	virtual void instance_free_custom_data(InstanceBase *p_instance) = 0;
-	virtual void instance_custom_data_update_lights(InstanceBase *p_instance) = 0;
-	virtual void instance_custom_data_update_reflection_probes(InstanceBase *p_instance) = 0;
-	virtual void instance_custom_data_update_gi_probes(InstanceBase *p_instance) = 0;
-	virtual void instance_custom_data_update_lightmap(InstanceBase *p_instance) = 0;
-	virtual void instance_custom_data_update_transform(InstanceBase *p_instance) = 0;
-
 	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, VS::ViewportMSAA p_msaa) = 0;
 
@@ -442,7 +418,6 @@ public:
 	virtual void light_set_use_gi(RID p_light, bool p_enable) = 0;
 
 	virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) = 0;
-	virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) = 0;
 
 	virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) = 0;
 	virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;

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

@@ -2375,7 +2375,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
 			attachments.push_back(af_color);
 
 			RD::AttachmentFormat af_depth;
-			af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT;
+			af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
 			af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
 
 			attachments.push_back(af_depth);

+ 48 - 1
servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp

@@ -39,7 +39,23 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) {
 	return uniform_set;
 }
 
-void RasterizerEffectsRD::copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
+void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y) {
+
+	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+	if (p_flip_y) {
+		blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
+	}
+
+	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, Vector<Color>(), p_rect);
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+	RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+	RD::get_singleton()->draw_list_draw(draw_list, true);
+	RD::get_singleton()->draw_list_end();
+}
+
+void RasterizerEffectsRD::region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
 
 	zeromem(&blur.push_constant, sizeof(BlurPushConstant));
 
@@ -164,6 +180,23 @@ void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_frameb
 	RD::get_singleton()->draw_list_end();
 }
 
+void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) {
+
+	CopyToDPPushConstant push_constant;
+	push_constant.bias = p_bias;
+	push_constant.z_far = p_z_far;
+	push_constant.z_near = p_z_near;
+	push_constant.z_flip = p_dp_flip;
+
+	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, Vector<Color>(), p_rect);
+	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy.pipelines[COPY_MODE_CUBE_TO_DP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+	RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+	RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
+	RD::get_singleton()->draw_list_draw(draw_list, true);
+	RD::get_singleton()->draw_list_end();
+}
+
 void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
 
 	zeromem(&tonemap.push_constant, sizeof(TonemapPushConstant));
@@ -277,6 +310,20 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
 		}
 	}
 
+	{
+		// Initialize copier
+		Vector<String> copy_modes;
+		copy_modes.push_back("\n#define MODE_CUBE_TO_DP\n");
+
+		copy.shader.initialize(copy_modes);
+
+		copy.shader_version = copy.shader.version_create();
+
+		for (int i = 0; i < COPY_MODE_MAX; i++) {
+			copy.pipelines[i].setup(copy.shader.version_get_shader(copy.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+		}
+	}
+
 	RD::SamplerState sampler;
 	sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
 	sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;

+ 25 - 2
servers/visual/rasterizer_rd/rasterizer_effects_rd.h

@@ -4,6 +4,7 @@
 #include "core/math/camera_matrix.h"
 #include "render_pipeline_vertex_format_cache_rd.h"
 #include "servers/visual/rasterizer_rd/shaders/blur.glsl.gen.h"
+#include "servers/visual/rasterizer_rd/shaders/copy.glsl.gen.h"
 #include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
 #include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h"
 #include "servers/visual/rasterizer_rd/shaders/tonemap.glsl.gen.h"
@@ -36,7 +37,8 @@ class RasterizerEffectsRD {
 		BLUR_FLAG_USE_BLUR_SECTION = (1 << 1),
 		BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
 		BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
-		BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4)
+		BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4),
+		BLUR_FLAG_FLIP_Y = (1 << 5)
 	};
 
 	struct BlurPushConstant {
@@ -146,6 +148,25 @@ class RasterizerEffectsRD {
 		RenderPipelineVertexFormatCacheRD pipelines[TONEMAP_MODE_MAX];
 	} tonemap;
 
+	struct CopyToDPPushConstant {
+		float bias;
+		float z_far;
+		float z_near;
+		uint32_t z_flip;
+	};
+
+	enum CopyMode {
+		COPY_MODE_CUBE_TO_DP,
+		COPY_MODE_MAX
+	};
+
+	struct Copy {
+
+		CopyShaderRD shader;
+		RID shader_version;
+		RenderPipelineVertexFormatCacheRD pipelines[COPY_MODE_MAX];
+	} copy;
+
 	RID default_sampler;
 	RID index_buffer;
 	RID index_array;
@@ -155,11 +176,13 @@ class RasterizerEffectsRD {
 	RID _get_uniform_set_from_texture(RID p_texture);
 
 public:
-	void copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
+	void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
+	void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false);
 	void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
 	void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness);
 	void render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler);
 	void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
+	void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
 
 	struct TonemapSettings {
 

+ 511 - 186
servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp

@@ -67,6 +67,18 @@ static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_
 	p_array[11] = 0;
 }
 
+static _FORCE_INLINE_ void store_transform_3x3_430(const Transform &p_mtx, float *p_array) {
+	p_array[0] = p_mtx.basis.elements[0][0];
+	p_array[1] = p_mtx.basis.elements[1][0];
+	p_array[2] = p_mtx.basis.elements[2][0];
+	p_array[3] = p_mtx.basis.elements[0][1];
+	p_array[4] = p_mtx.basis.elements[1][1];
+	p_array[5] = p_mtx.basis.elements[2][1];
+	p_array[6] = p_mtx.basis.elements[0][2];
+	p_array[7] = p_mtx.basis.elements[1][2];
+	p_array[8] = p_mtx.basis.elements[2][2];
+}
+
 static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
 
 	for (int i = 0; i < 4; i++) {
@@ -296,8 +308,8 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
 						if (depth_draw == DEPTH_DRAW_OPAQUE) {
 							depth_stencil.enable_depth_write = false; //alpha does not draw depth
 						}
-					} else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS)) {
-						if (k == SHADER_VERSION_DEPTH_PASS) {
+					} else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS)) {
+						if (k == SHADER_VERSION_DEPTH_PASS || k == k == SHADER_VERSION_DEPTH_PASS_DP) {
 							//none, blend state contains nothing
 						} else {
 							blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
@@ -310,7 +322,7 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
 
 					if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
 						blend_state = blend_state_opaque;
-					} else if (k == SHADER_VERSION_DEPTH_PASS) {
+					} else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
 						//none, leave empty
 					} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
 						blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
@@ -583,60 +595,62 @@ bool RasterizerSceneForwardRD::free(RID p_rid) {
 	}
 	return false;
 }
-/// INSTANCE DATA ///
-
-void RasterizerSceneForwardRD::instance_create_custom_data(InstanceBase *p_instance) {
-	InstanceGeometryData *geom_data = memnew(InstanceGeometryData);
-	geom_data->ubo = RD::get_singleton()->uniform_buffer_create(sizeof(InstanceGeometryData::UBO));
-	geom_data->using_lightmap_gi = p_instance->lightmap.is_valid();
-	p_instance->custom_data = geom_data;
-}
 
-void RasterizerSceneForwardRD::instance_free_custom_data(InstanceBase *p_instance) {
-	InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
-	ERR_FAIL_COND(!geom_data);
-	RD::get_singleton()->free(geom_data->ubo);
-	//uniform sets are freed as dependencies
-	memdelete(geom_data);
-	p_instance->custom_data = nullptr;
-}
+void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, int p_element_count) {
 
-void RasterizerSceneForwardRD::instance_custom_data_update_lights(InstanceBase *p_instance) {
-	//unused
-}
-
-void RasterizerSceneForwardRD::instance_custom_data_update_reflection_probes(InstanceBase *p_instance) {
-	//unused
-}
-void RasterizerSceneForwardRD::instance_custom_data_update_lightmap(InstanceBase *p_instance) {
-	InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
-	ERR_FAIL_COND(!geom_data);
+	for (int i = 0; i < p_element_count; i++) {
 
-	geom_data->using_lightmap_gi = p_instance->lightmap.is_valid();
+		const RenderList::Element *e = p_elements[i];
+		InstanceData &id = scene_state.instances[i];
+		store_transform(e->instance->transform, id.transform);
+		store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
+		id.flags = 0;
+		id.mask = e->instance->layer_mask;
+
+		//forward
+
+		uint32_t reflection_count = 0;
+		uint32_t omni_count = 0;
+		uint32_t spot_count = 0;
+		uint32_t decal_count = 0;
+
+		if (!e->instance->light_instances.empty()) {
+			uint32_t light_count = e->instance->light_instances.size();
+			const RID *light_ptrs = e->instance->light_instances.ptr();
+
+			for (uint32_t j = 0; j < light_count; j++) {
+				if (render_pass != light_instance_get_render_pass(light_ptrs[j])) {
+					continue; //not rendered this frame
+				}
 
-	if (geom_data->uniform_set_gi.is_valid() && RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
-		RD::get_singleton()->free(geom_data->uniform_set_gi);
-	}
-	geom_data->uniform_set_gi = RID();
-}
+				RID base = light_instance_get_base_light(light_ptrs[j]);
 
-void RasterizerSceneForwardRD::instance_custom_data_update_gi_probes(InstanceBase *p_instance) {
-	InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
-	ERR_FAIL_COND(!geom_data);
+				uint32_t mask = storage->light_get_cull_mask(base);
+				if (!(mask & id.mask)) {
+					continue; //masked
+				}
 
-	geom_data->using_vct_gi = p_instance->gi_probe_instances.size();
+				if (storage->light_get_type(base) == VS::LIGHT_OMNI) {
+					if (omni_count < 8) {
+						id.omni_light_indices[omni_count] = light_instance_get_index(light_ptrs[j]);
+						omni_count++;
+					}
+				} else {
+					if (spot_count < 8) {
+						id.omni_light_indices[spot_count] = light_instance_get_index(light_ptrs[j]);
+						spot_count++;
+					}
+				}
+			}
+		}
 
-	if (geom_data->uniform_set_gi.is_valid() && RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
-		RD::get_singleton()->free(geom_data->uniform_set_gi);
+		id.flags |= reflection_count;
+		id.flags |= omni_count << 3;
+		id.flags |= spot_count << 6;
+		id.flags |= decal_count << 9;
 	}
-	geom_data->uniform_set_gi = RID();
-}
-
-void RasterizerSceneForwardRD::instance_custom_data_update_transform(InstanceBase *p_instance) {
-	InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
-	ERR_FAIL_COND(!geom_data);
 
-	geom_data->ubo_dirty = true;
+	RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true);
 }
 
 /// RENDERING ///
@@ -669,7 +683,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
 		//find cull variant
 		ShaderData::CullVariant cull_variant;
 
-		if (p_pass_mode == PASS_MODE_SHADOW && e->instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
+		if ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
 			cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
 		} else {
 			bool mirror = e->instance->mirror;
@@ -700,59 +714,42 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
 			}
 		}
 
-		InstanceGeometryData *geom_data = (InstanceGeometryData *)e->instance->custom_data;
-
 		ShaderVersion shader_version;
-		RID instance_uniform_set;
 
 		switch (p_pass_mode) {
 			case PASS_MODE_COLOR:
 			case PASS_MODE_COLOR_TRANSPARENT: {
 
-				if (p_no_gi) {
-					instance_uniform_set = geom_data->uniform_set_base;
-					shader_version = SHADER_VERSION_COLOR_PASS;
-				} else if (geom_data->using_lightmap_gi) {
-					instance_uniform_set = geom_data->uniform_set_gi;
+				if (e->uses_lightmap) {
 					shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS;
-				} else if (geom_data->using_vct_gi) {
-					instance_uniform_set = geom_data->uniform_set_gi;
+				} else if (e->uses_vct) {
 					shader_version = SHADER_VERSION_VCT_COLOR_PASS;
 				} else {
-					instance_uniform_set = geom_data->uniform_set_gi;
 					shader_version = SHADER_VERSION_COLOR_PASS;
 				}
+
 			} break;
 			case PASS_MODE_COLOR_SPECULAR: {
-				if (p_no_gi) {
-					instance_uniform_set = geom_data->uniform_set_base;
-					shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
-				} else if (geom_data->using_lightmap_gi) {
-					instance_uniform_set = geom_data->uniform_set_gi;
+				if (e->uses_lightmap) {
 					shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
-				} else if (geom_data->using_vct_gi) {
-					instance_uniform_set = geom_data->uniform_set_gi;
+				} else if (e->uses_vct) {
 					shader_version = SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR;
 				} else {
-					instance_uniform_set = geom_data->uniform_set_gi;
 					shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
 				}
 			} break;
-			case PASS_MODE_SHADOW: {
-				shader_version = SHADER_VERSION_DEPTH_PASS;
-				instance_uniform_set = geom_data->uniform_set_base;
-			} break;
+			case PASS_MODE_SHADOW:
 			case PASS_MODE_DEPTH: {
 				shader_version = SHADER_VERSION_DEPTH_PASS;
-				instance_uniform_set = geom_data->uniform_set_base;
+			} break;
+			case PASS_MODE_SHADOW_DP: {
+				shader_version = SHADER_VERSION_DEPTH_PASS_DP;
 			} break;
 			case PASS_MODE_DEPTH_NORMAL: {
 				shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL;
-				instance_uniform_set = geom_data->uniform_set_base;
 			} break;
 			case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
 				shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
-				instance_uniform_set = geom_data->uniform_set_base;
 			} break;
 		}
 
@@ -812,8 +809,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
 			prev_material = material;
 		}
 
-		RD::get_singleton()->draw_list_bind_uniform_set(draw_list, instance_uniform_set, 3);
-
+		push_constant.index = i;
 		RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant));
 
 		switch (e->instance->base_type) {
@@ -836,10 +832,13 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
 	}
 }
 
-void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) {
+void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas) {
 
-	CameraMatrix projection = p_cam_projection;
-	projection.flip_y(); // Vulkan and modern APIs use Y-Down
+	//CameraMatrix projection = p_cam_projection;
+	//projection.flip_y(); // Vulkan and modern APIs use Y-Down
+	CameraMatrix correction;
+	correction.set_depth_correction();
+	CameraMatrix projection = correction * p_cam_projection;
 
 	//store camera into ubo
 	store_camera(projection, scene_state.ubo.projection_matrix);
@@ -847,6 +846,19 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
 	store_transform(p_cam_transform, scene_state.ubo.camera_matrix);
 	store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
 
+	scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
+	scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
+
+	if (p_shadow_atlas.is_valid()) {
+		Vector2 sas = shadow_atlas_get_size(p_shadow_atlas);
+		scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x;
+		scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y;
+	}
+	{
+		Vector2 dss = directional_shadow_get_size();
+		scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x;
+		scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y;
+	}
 	//time global variables
 	scene_state.ubo.time = time;
 
@@ -863,7 +875,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
 		//ambient
 		if (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && (env_bg == VS::ENV_BG_CLEAR_COLOR || env_bg == VS::ENV_BG_COLOR)) {
 
-			Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? storage->render_target_get_clear_request_color(p_render_target) : environment_get_bg_color(p_environment);
+			Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? (p_render_target.is_valid() ? storage->render_target_get_clear_request_color(p_render_target) : Color(0, 0, 0)) : environment_get_bg_color(p_environment);
 			color = color.to_linear();
 
 			scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
@@ -1024,7 +1036,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
 	RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
 }
 
-void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode) {
+void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
 
 	RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
 
@@ -1047,18 +1059,18 @@ void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t
 
 	ERR_FAIL_COND(!material);
 
-	_add_geometry_with_material(p_instance, p_surface, material, p_pass_mode);
+	_add_geometry_with_material(p_instance, p_surface, material, p_pass_mode, p_geometry_index);
 
 	while (material->next_pass.is_valid()) {
 
 		material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D);
 		if (!material || !material->shader_data->valid)
 			break;
-		_add_geometry_with_material(p_instance, p_surface, material, p_pass_mode);
+		_add_geometry_with_material(p_instance, p_surface, material, p_pass_mode, p_geometry_index);
 	}
 }
 
-void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode) {
+void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
 
 	bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
 	bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
@@ -1120,8 +1132,11 @@ void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_insta
 			e->material->shader_data->index = scene_state.current_shader_index++;
 		}
 	}
-
+	e->geometry_index = p_geometry_index;
 	e->material_index = e->material->index;
+	e->uses_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH;
+	e->uses_lightmap = e->instance->lightmap.is_valid();
+	e->uses_vct = e->instance->gi_probe_instances.size();
 	e->shader_index = e->shader_index;
 	e->depth_layer = e->instance->depth_layer;
 	e->priority = p_material->priority;
@@ -1140,89 +1155,14 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i
 	scene_state.used_normal_texture = false;
 	scene_state.used_depth_texture = false;
 
+	uint32_t geometry_index = 0;
+
 	//fill list
 
 	for (int i = 0; i < p_cull_count; i++) {
 
 		InstanceBase *inst = p_cull_result[i];
 
-		InstanceGeometryData *geom_data = (InstanceGeometryData *)inst->custom_data;
-
-		ERR_CONTINUE(!geom_data);
-
-		if (geom_data->ubo_dirty) {
-			//ubo marked dirty, must be updated
-			InstanceGeometryData::UBO ubo;
-			store_transform(inst->transform, ubo.transform);
-			store_transform_3x3(inst->transform.basis.inverse().transposed(), ubo.normal_transform);
-			ubo.flags = 0;
-			ubo.pad[0] = 0;
-			ubo.pad[1] = 0;
-			ubo.pad[2] = 0;
-			RD::get_singleton()->buffer_update(geom_data->ubo, 0, sizeof(InstanceGeometryData::UBO), &ubo, true);
-		}
-
-		if (p_no_gi) {
-			if (geom_data->uniform_set_base.is_null() || !RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_base)) {
-
-				Vector<RD::Uniform> uniforms;
-				{
-					RD::Uniform u;
-					u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-					u.binding = 0;
-					u.ids.push_back(geom_data->ubo);
-					uniforms.push_back(u);
-				}
-				{
-					RD::Uniform u;
-					u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
-					u.binding = 1;
-					u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
-					uniforms.push_back(u);
-				}
-
-				geom_data->uniform_set_base = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 3);
-			}
-		} else {
-			if (geom_data->uniform_set_gi.is_null() || !RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
-
-				Vector<RD::Uniform> uniforms;
-				{
-					RD::Uniform u;
-					u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
-					u.binding = 0;
-					u.ids.push_back(geom_data->ubo);
-					uniforms.push_back(u);
-				}
-				{
-					RD::Uniform u;
-					u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
-					u.binding = 1;
-					u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
-					uniforms.push_back(u);
-				}
-
-				if (geom_data->using_lightmap_gi) {
-					{
-						RD::Uniform u;
-						u.type = RD::UNIFORM_TYPE_TEXTURE;
-						u.binding = 2;
-#ifndef _MSC_VER
-#warning Need to put actual lightmap or lightmap capture texture if exists
-#endif
-						u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
-						uniforms.push_back(u);
-					}
-				} else if (geom_data->using_vct_gi) {
-#ifndef _MSC_VER
-#warning Need to put actual vct textures here
-#endif
-				}
-
-				geom_data->uniform_set_gi = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 3);
-			}
-		}
-
 		//add geometry for drawing
 		switch (inst->base_type) {
 
@@ -1242,7 +1182,8 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i
 
 					RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
 
-					_add_geometry(inst, j, material, p_pass_mode);
+					uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index);
+					_add_geometry(inst, j, material, p_pass_mode, surface_index);
 				}
 
 				//mesh->last_pass=frame;
@@ -1341,11 +1282,207 @@ void RasterizerSceneForwardRD::_draw_sky(RD::DrawListID p_draw_list, RD::Framebu
 	storage->get_effects()->render_panorama(p_draw_list, p_fb_format, panorama, camera, sky_transform, 1.0, multiplier);
 }
 
-void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
 
-	RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
+	for (uint32_t i = 0; i < p_reflection_probe_cull_count; i++) {
+
+		RID rpi = p_reflection_probe_cull_result[i];
+
+		if (i >= scene_state.max_reflections) {
+			reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
+			continue;
+		}
+
+		reflection_probe_instance_set_render_index(rpi, i);
+
+		RID base_probe = reflection_probe_instance_get_probe(rpi);
+
+		ReflectionData &reflection_ubo = scene_state.reflections[i];
+
+		Vector3 extents = storage->reflection_probe_get_extents(base_probe);
+
+		reflection_ubo.box_extents[0] = extents.x;
+		reflection_ubo.box_extents[1] = extents.y;
+		reflection_ubo.box_extents[2] = extents.z;
+		reflection_ubo.box_extents[3] = 0;
+
+		Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
+
+		reflection_ubo.box_offset[0] = origin_offset.x;
+		reflection_ubo.box_offset[1] = origin_offset.y;
+		reflection_ubo.box_offset[2] = origin_offset.z;
+		reflection_ubo.box_offset[3] = 0;
+
+		float intensity = storage->reflection_probe_get_intensity(base_probe);
+		bool interior = storage->reflection_probe_is_interior(base_probe);
+		bool box_projection = storage->reflection_probe_is_box_projection(base_probe);
+
+		reflection_ubo.params[0] = intensity;
+		reflection_ubo.params[1] = 0;
+		reflection_ubo.params[2] = interior ? 1.0 : 0.0;
+		reflection_ubo.params[3] = box_projection ? 1.0 : 0.0;
+
+		if (interior) {
+			Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear();
+			float interior_ambient_energy = storage->reflection_probe_get_interior_ambient_energy(base_probe);
+			float interior_ambient_probe_contrib = storage->reflection_probe_get_interior_ambient_probe_contribution(base_probe);
+			reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
+			reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
+			reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
+			reflection_ubo.ambient[3] = interior_ambient_probe_contrib;
+		} else {
+			Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear();
+			if (is_environment(p_environment)) {
+				Color env_ambient_color = environment_get_ambient_light_color(p_environment).to_linear();
+				float env_ambient_energy = environment_get_ambient_light_ambient_energy(p_environment);
+				ambient_linear = env_ambient_color;
+				ambient_linear.r *= env_ambient_energy;
+				ambient_linear.g *= env_ambient_energy;
+				ambient_linear.b *= env_ambient_energy;
+			}
+
+			reflection_ubo.ambient[0] = ambient_linear.r;
+			reflection_ubo.ambient[1] = ambient_linear.g;
+			reflection_ubo.ambient[2] = ambient_linear.b;
+			reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light
+		}
+
+		Transform transform = reflection_probe_instance_get_transform(rpi);
+		Transform proj = (p_camera_inverse_transform * transform).inverse();
+		store_transform(proj, reflection_ubo.local_matrix);
+	}
+
+	if (p_reflection_probe_cull_count) {
+		RD::get_singleton()->buffer_update(scene_state.reflection_buffer, 0, MIN(scene_state.max_reflections, p_reflection_probe_cull_count) * sizeof(ReflectionData), scene_state.reflections, true);
+	}
+}
+
+void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas) {
+
+	uint32_t light_count = 0;
+	scene_state.ubo.directional_light_count = 0;
+
+	for (int i = 0; i < p_light_cull_count; i++) {
+
+		RID li = p_light_cull_result[i];
+		RID base = light_instance_get_base_light(li);
+
+		ERR_CONTINUE(base.is_null());
+
+		VS::LightType type = storage->light_get_type(base);
+		switch (type) {
+
+			case VS::LIGHT_DIRECTIONAL: {
+
+				if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
+					continue;
+				}
+			} break;
+			case VS::LIGHT_SPOT:
+			case VS::LIGHT_OMNI: {
+
+				if (light_count >= scene_state.max_lights) {
+					continue;
+				}
+
+				Transform light_transform = light_instance_get_base_transform(li);
+
+				LightData &light_data = scene_state.lights[light_count];
+
+				float sign = storage->light_is_negative(base) ? -1 : 1;
+				Color linear_col = storage->light_get_color(base).to_linear();
+
+				light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, VS::LIGHT_PARAM_ATTENUATION));
+				light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, VS::LIGHT_PARAM_ENERGY) * Math_PI);
+
+				light_data.color_specular[0] = CLAMP(uint32_t(linear_col.r * 255), 0, 255);
+				light_data.color_specular[1] = CLAMP(uint32_t(linear_col.g * 255), 0, 255);
+				light_data.color_specular[2] = CLAMP(uint32_t(linear_col.b * 255), 0, 255);
+				light_data.color_specular[3] = CLAMP(uint32_t(storage->light_get_param(base, VS::LIGHT_PARAM_SPECULAR) * 255), 0, 255);
+
+				light_data.inv_radius = 1.0 / MAX(0.001, storage->light_get_param(base, VS::LIGHT_PARAM_RANGE));
+
+				Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin);
+
+				light_data.position[0] = pos.x;
+				light_data.position[1] = pos.y;
+				light_data.position[2] = pos.z;
+
+				Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized();
+
+				light_data.direction[0] = direction.x;
+				light_data.direction[1] = direction.y;
+				light_data.direction[2] = direction.z;
+
+				light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ATTENUATION));
+				light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ANGLE))));
+
+				light_data.mask = storage->light_get_cull_mask(base);
+
+				Color shadow_color = storage->light_get_shadow_color(base);
+
+				bool has_shadow = storage->light_has_shadow(base);
+				light_data.shadow_color_enabled[0] = CLAMP(uint32_t(shadow_color.r * 255), 0, 255);
+				light_data.shadow_color_enabled[1] = CLAMP(uint32_t(shadow_color.g * 255), 0, 255);
+				light_data.shadow_color_enabled[2] = CLAMP(uint32_t(shadow_color.b * 255), 0, 255);
+				light_data.shadow_color_enabled[3] = has_shadow ? 255 : 0;
+
+				light_data.atlas_rect[0] = 0;
+				light_data.atlas_rect[1] = 0;
+				light_data.atlas_rect[2] = 0;
+				light_data.atlas_rect[3] = 0;
+
+				if (storage->light_has_shadow(base) && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
+					// fill in the shadow information
+
+					Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
+
+					if (type == VS::LIGHT_OMNI) {
+
+						light_data.atlas_rect[0] = rect.position.x;
+						light_data.atlas_rect[1] = rect.position.y;
+						light_data.atlas_rect[2] = rect.size.width;
+						light_data.atlas_rect[3] = rect.size.height * 0.5;
+
+						Transform proj = (p_camera_inverse_transform * light_transform).inverse();
+
+						store_transform(proj, light_data.shadow_matrix);
+					} else if (type == VS::LIGHT_SPOT) {
 
-	ERR_FAIL_COND(!render_buffer); //bug out for now
+						Transform modelview = (p_camera_inverse_transform * light_transform).inverse();
+						CameraMatrix bias;
+						bias.set_light_bias();
+						CameraMatrix rectm;
+						rectm.set_light_atlas_rect(rect);
+
+						CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview;
+						store_camera(shadow_mtx, light_data.shadow_matrix);
+					}
+				}
+
+				light_instance_set_index(li, light_count);
+
+				light_count++;
+			} break;
+		}
+
+		light_instance_set_render_pass(li, render_pass);
+
+		//update UBO for forward rendering, blit to texture for clustered
+	}
+
+	if (light_count) {
+		RD::get_singleton()->buffer_update(scene_state.light_buffer, 0, sizeof(LightData) * light_count, scene_state.lights, true);
+	}
+
+	if (scene_state.ubo.directional_light_count) {
+		RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * light_count, scene_state.directional_lights, true);
+	}
+}
+
+void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+
+	RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
 
 	//first of all, make a new render pass
 	render_pass++;
@@ -1388,14 +1525,34 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 	scene_state.ubo.viewport_size[1] = vp_he.y;
 
 	RID render_target;
+	Size2 screen_pixel_size;
+	RID opaque_framebuffer;
+	RID alpha_framebuffer;
 
 	if (render_buffer) {
-		scene_state.ubo.screen_pixel_size[0] = 1.0 / render_buffer->width;
-		scene_state.ubo.screen_pixel_size[1] = 1.0 / render_buffer->height;
+		screen_pixel_size.width = 1.0 / render_buffer->width;
+		screen_pixel_size.height = 1.0 / render_buffer->height;
 		render_target = render_buffer->render_target;
+
+		opaque_framebuffer = render_buffer->color_fb;
+		alpha_framebuffer = opaque_framebuffer;
+
+	} else if (p_reflection_probe.is_valid()) {
+		uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe);
+		screen_pixel_size.width = 1.0 / resolution;
+		screen_pixel_size.height = 1.0 / resolution;
+
+		opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass);
+		alpha_framebuffer = opaque_framebuffer;
+
+	} else {
+		ERR_FAIL(); //bug?
 	}
 
-	_setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid());
+	_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas);
+	_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
+	_setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas);
+
 #if 0
 	for (int i = 0; i < p_light_cull_count; i++) {
 
@@ -1771,10 +1928,12 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 		}
 	}
 
-	_setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap);
+	_setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, RID());
 
 	render_list.sort_by_key(false);
 
+	_fill_instances(render_list.elements, render_list.element_count);
+
 	bool can_continue = true; //unless the middle buffers are needed
 	bool using_separate_specular = false;
 
@@ -1782,14 +1941,14 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 		//regular forward for now
 		Vector<Color> c;
 		c.push_back(clear_color.to_linear());
-		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, keep_color ? RD::INITIAL_ACTION_KEEP_COLOR : RD::INITIAL_ACTION_CLEAR, (can_continue || draw_sky) ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c);
-		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
+		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP_COLOR : RD::INITIAL_ACTION_CLEAR, (can_continue || draw_sky) ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c);
+		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
 		RD::get_singleton()->draw_list_end();
 	}
 
 	if (draw_sky) {
-		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
-		_draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), p_environment, p_cam_projection, p_cam_transform, 1.0);
+		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
+		_draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), p_environment, p_cam_projection, p_cam_transform, 1.0);
 		RD::get_singleton()->draw_list_end();
 
 		if (using_separate_specular && !can_continue) {
@@ -1887,9 +2046,11 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 #endif
 	render_list.sort_by_reverse_depth_and_priority(true);
 
+	_fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count);
+
 	{
-		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP_COLOR_AND_DEPTH, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
-		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
+		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP_COLOR_AND_DEPTH, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
+		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
 		RD::get_singleton()->draw_list_end();
 	}
 
@@ -1907,7 +2068,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 	}
 #endif
 	if (p_reflection_probe.is_valid()) {
-		//rendering a probe, do no more!
+		//was rendering a probe, so do no more
 		return;
 	}
 
@@ -1931,6 +2092,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 
 	storage->render_target_disable_clear_request(render_buffer->render_target);
 
+	if (true) {
+		if (p_shadow_atlas.is_valid()) {
+			RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
+			Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
+
+			effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2));
+		}
+	}
+
 #if 0
 	_post_process(env, p_cam_projection);
 	// Needed only for debugging
@@ -1988,8 +2158,38 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
 	//disable all stuff
 #endif
 }
+void RasterizerSceneForwardRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip) {
 
-void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap) {
+	render_pass++;
+
+	scene_state.ubo.shadow_z_offset = p_bias;
+	scene_state.ubo.shadow_z_slope_scale = p_normal_bias;
+	scene_state.ubo.z_far = p_zfar;
+	scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+
+	_setup_environment(RID(), RID(), p_projection, p_transform, true, Vector2(1, 1), RID());
+
+	render_list.clear();
+
+	PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
+
+	_fill_render_list(p_cull_result, p_cull_count, pass_mode, true);
+
+	_setup_render_base_uniform_set(RID(), RID(), RID(), RID(), RID(), RID(), RID());
+
+	render_list.sort_by_key(false);
+
+	_fill_instances(render_list.elements, render_list.element_count);
+
+	{
+		//regular forward for now
+		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
+		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true);
+		RD::get_singleton()->draw_list_end();
+	}
+}
+
+void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap, RID p_shadow_atlas, RID p_reflection_atlas) {
 
 	if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
 		RD::get_singleton()->free(render_base_uniform_set);
@@ -2065,20 +2265,79 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
 	{
 		RD::Uniform u;
 		u.binding = 7;
+		u.type = RD::UNIFORM_TYPE_SAMPLER;
+		u.ids.push_back(shadow_sampler);
+		uniforms.push_back(u);
+	}
+
+	{
+		RD::Uniform u;
+		u.binding = 8;
 		u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
 		u.ids.push_back(scene_state.uniform_buffer);
 		uniforms.push_back(u);
 	}
+	{
+		RD::Uniform u;
+		u.binding = 9;
+		u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+		u.ids.push_back(scene_state.instance_buffer);
+		uniforms.push_back(u);
+	}
+
+	{
+		RD::Uniform u;
+		u.binding = 10;
+		u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+		u.ids.push_back(scene_state.reflection_buffer);
+		uniforms.push_back(u);
+	}
+
+	{
+		RD::Uniform u;
+		u.binding = 11;
+		u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+		u.ids.push_back(scene_state.light_buffer);
+		uniforms.push_back(u);
+	}
+
+	{
+		RD::Uniform u;
+		u.binding = 12;
+		u.type = RD::UNIFORM_TYPE_TEXTURE;
+		if (p_shadow_atlas.is_valid()) {
+			u.ids.push_back(shadow_atlas_get_texture(p_shadow_atlas));
+		} else {
+			u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+		}
+		uniforms.push_back(u);
+	}
+
+	{
+		RD::Uniform u;
+		u.binding = 13;
+		u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+		u.ids.push_back(scene_state.directional_light_buffer);
+		uniforms.push_back(u);
+	}
+
+	{
+		RD::Uniform u;
+		u.binding = 14;
+		u.type = RD::UNIFORM_TYPE_TEXTURE;
+		if (directional_shadow_get_texture().is_valid()) {
+			u.ids.push_back(directional_shadow_get_texture());
+		} else {
+			u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+		}
+		uniforms.push_back(u);
+	}
 
 	render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0);
 }
 
 RasterizerSceneForwardRD *RasterizerSceneForwardRD::singleton = NULL;
 
-void RasterizerSceneForwardRD::set_scene_pass(uint64_t p_pass) {
-	scene_pass = p_pass;
-}
-
 void RasterizerSceneForwardRD::set_time(double p_time) {
 	time = p_time;
 }
@@ -2097,8 +2356,53 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
 			defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
 		}
 
+		uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
+
+		if (textures_per_stage <= 16) {
+			//ARM pretty much, and very old Intel GPUs under Linux
+			scene_state.max_reflection_probes_per_instance = 4; //sad
+		} else {
+			//maximum 8
+			scene_state.max_reflection_probes_per_instance = 8;
+		}
+
+		defines += "\n#define MAX_REFLECTION_PROBES " + itos(scene_state.max_reflection_probes_per_instance) + "\n";
+
+		uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
+
+		{ //reflections
+			uint32_t reflection_buffer_size;
+			if (uniform_max_size < 65536) {
+				//Yes, you guessed right, ARM again
+				reflection_buffer_size = uniform_max_size;
+			} else {
+				reflection_buffer_size = 65536;
+			}
+
+			scene_state.max_reflections = reflection_buffer_size / sizeof(ReflectionData);
+			scene_state.reflections = memnew_arr(ReflectionData, scene_state.max_reflections);
+			scene_state.reflection_buffer = RD::get_singleton()->uniform_buffer_create(reflection_buffer_size);
+			defines += "\n#define MAX_REFLECTION_DATA_STRUCTS " + itos(scene_state.max_reflections) + "\n";
+		}
+
+		{ //lights
+			scene_state.max_lights = MIN(65536, uniform_max_size) / sizeof(LightData);
+			uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData);
+			print_line("ID: " + itos(sizeof(InstanceData)));
+			scene_state.lights = memnew_arr(LightData, scene_state.max_lights);
+			scene_state.light_buffer = RD::get_singleton()->uniform_buffer_create(light_buffer_size);
+			defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
+
+			scene_state.max_directional_lights = 4;
+			uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData);
+			scene_state.directional_lights = memnew_arr(DirectionalLightData, scene_state.max_directional_lights);
+			scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
+			defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(scene_state.max_directional_lights) + "\n";
+		}
+
 		Vector<String> shader_versions;
 		shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
+		shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n");
 		shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_BUFFER\n");
 		shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_ROUGHNESS_BUFFER\n");
 		shader_versions.push_back("");
@@ -2198,7 +2502,7 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
 		actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
 
 		actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
-		actions.usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n";
+		actions.usage_defines["TRANSMISSION"] = "#define LIGHT_TRANSMISSION_USED\n";
 		actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
 		actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
 
@@ -2249,11 +2553,17 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
 	}
 
 	//render list
-	render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)256000);
+	render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000);
 	render_list.init();
-	scene_pass = 0;
 	render_pass = 0;
 
+	{
+
+		scene_state.max_instances = render_list.max_elements;
+		scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances);
+		scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances);
+	}
+
 	scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
 
 	{
@@ -2266,6 +2576,16 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
 		MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D);
 		default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
 	}
+
+	{
+
+		RD::SamplerState sampler;
+		sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+		sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
+		sampler.enable_compare = true;
+		sampler.compare_op = RD::COMPARE_OP_LESS;
+		shadow_sampler = RD::get_singleton()->sampler_create(sampler);
+	}
 }
 
 RasterizerSceneForwardRD::~RasterizerSceneForwardRD() {
@@ -2273,4 +2593,9 @@ RasterizerSceneForwardRD::~RasterizerSceneForwardRD() {
 	if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
 		RD::get_singleton()->free(render_base_uniform_set);
 	}
+
+	{
+		RD::get_singleton()->free(scene_state.reflection_buffer);
+		memdelete_arr(scene_state.reflections);
+	}
 }

+ 100 - 49
servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h

@@ -42,6 +42,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 
 	enum ShaderVersion {
 		SHADER_VERSION_DEPTH_PASS,
+		SHADER_VERSION_DEPTH_PASS_DP,
 		SHADER_VERSION_DEPTH_PASS_WITH_NORMAL,
 		SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
 		SHADER_VERSION_COLOR_PASS,
@@ -174,37 +175,11 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 		return static_cast<RasterizerSceneForwardRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
 	}
 
-	/* Instance Custom Data */
-
-	struct InstanceGeometryData : public InstanceCustomData {
-
-		struct UBO {
-			float transform[16];
-			float normal_transform[12];
-			uint32_t flags;
-			uint32_t pad[3];
-		};
-
-		RID ubo;
-		RID uniform_set_base;
-		RID uniform_set_gi;
-
-		bool ubo_dirty = true;
-		bool using_lightmap_gi = false;
-		bool using_vct_gi = false;
-	};
-
 	/* Push Constant */
 
 	struct PushConstant {
-		uint32_t reflection_probe_count;
-		uint32_t omni_light_count;
-		uint32_t spot_light_count;
-		uint32_t decal_count;
-		float reflection_probe_indices[4];
-		float omni_light_indices[4];
-		float spot_light_indices[4];
-		float decal_indices[4];
+		uint32_t index;
+		uint32_t pad[3];
 	};
 
 	/* Framebuffer */
@@ -227,11 +202,65 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 
 	virtual RenderBufferData *_create_render_buffer_data();
 
+	RID shadow_sampler;
 	RID render_base_uniform_set;
-	void _setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap);
+	void _setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap, RID p_shadow_atlas, RID p_reflection_atlas);
 
 	/* Scene State UBO */
 
+	struct ReflectionData { //should always be 128 bytes
+		float box_extents[4];
+		float box_offset[4];
+		float params[4]; // intensity, 0, interior , boxproject
+		float ambient[4]; // ambient color, energy
+		float local_matrix[16]; // up to here for spot and omni, rest is for directional
+	};
+
+	struct LightData {
+		float position[3];
+		float inv_radius;
+		float direction[3];
+		uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
+		uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
+		uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
+		uint32_t mask;
+		uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
+		float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
+		float shadow_matrix[16];
+	};
+
+	struct DirectionalLightData {
+
+		float direction[3];
+		float energy;
+		float color[3];
+		float specular;
+		uint32_t mask;
+		uint32_t pad[3];
+		float shadow_color[3];
+		uint32_t shadow_enabled;
+		float shadow_atlas_rect[4];
+		float shadow_split_offsets[4];
+		float shadow_matrix1[16];
+		float shadow_matrix2[16];
+		float shadow_matrix3[16];
+		float shadow_matrix4[16];
+	};
+
+	struct InstanceData {
+		float transform[16];
+		float normal_transform[16];
+		uint32_t flags;
+		uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer
+		uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
+		uint32_t mask;
+
+		uint16_t reflection_probe_indices[8];
+		uint16_t omni_light_indices[8];
+		uint16_t spot_light_indices[8];
+		uint16_t decal_indices[8];
+	};
+
 	struct SceneState {
 		struct UBO {
 			float projection_matrix[16];
@@ -257,12 +286,37 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 			uint32_t use_reflection_cubemap;
 
 			float radiance_inverse_xform[12];
+
+			float shadow_atlas_pixel_size[2];
+			float directional_shadow_pixel_size[2];
+
+			uint32_t directional_light_count;
+			float dual_paraboloid_side;
+			float z_far;
+			uint32_t pad[1];
 		};
 
 		UBO ubo;
 
 		RID uniform_buffer;
 
+		ReflectionData *reflections;
+		uint32_t max_reflections;
+		RID reflection_buffer;
+		uint32_t max_reflection_probes_per_instance;
+
+		LightData *lights;
+		uint32_t max_lights;
+		RID light_buffer;
+
+		DirectionalLightData *directional_lights;
+		uint32_t max_directional_lights;
+		RID directional_light_buffer;
+
+		RID instance_buffer;
+		InstanceData *instances;
+		uint32_t max_instances;
+
 		bool used_screen_texture = false;
 		bool used_normal_texture = false;
 		bool used_depth_texture = false;
@@ -283,10 +337,14 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 			union {
 				struct {
 					//from least significant to most significant in sort, TODO: should be endian swapped on big endian
-					uint64_t material_index : 20;
-					uint64_t shader_index : 20;
-					uint64_t priority : 16;
-					uint64_t depth_layer : 8;
+					uint64_t geometry_index : 20;
+					uint64_t material_index : 15;
+					uint64_t shader_index : 12;
+					uint64_t uses_instancing : 1;
+					uint64_t uses_vct : 1;
+					uint64_t uses_lightmap : 1;
+					uint64_t depth_layer : 4;
+					uint64_t priority : 8;
 				};
 
 				uint64_t sort_key;
@@ -407,7 +465,6 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 	RenderList render_list;
 
 	static RasterizerSceneForwardRD *singleton;
-	uint64_t scene_pass;
 	uint64_t render_pass;
 	double time;
 	RID default_shader;
@@ -419,39 +476,33 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 		PASS_MODE_COLOR_SPECULAR,
 		PASS_MODE_COLOR_TRANSPARENT,
 		PASS_MODE_SHADOW,
+		PASS_MODE_SHADOW_DP,
 		PASS_MODE_DEPTH,
 		PASS_MODE_DEPTH_NORMAL,
 		PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
 	};
 
-	void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog);
+	void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas);
+	void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas);
+	void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
 
+	void _fill_instances(RenderList::Element **p_elements, int p_element_count);
 	void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi);
-	_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode);
-	_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode);
+	_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index);
+	_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode, uint32_t p_geometry_index);
 
 	void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
 
 	void _draw_sky(RD::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha);
 
 protected:
-	virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+	virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
 
 public:
-	virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
-
-	virtual void set_scene_pass(uint64_t p_pass);
 	virtual void set_time(double p_time);
 	virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {}
 
-	virtual void instance_create_custom_data(InstanceBase *p_instance);
-	virtual void instance_free_custom_data(InstanceBase *p_instance);
-	virtual void instance_custom_data_update_lights(InstanceBase *p_instance);
-	virtual void instance_custom_data_update_reflection_probes(InstanceBase *p_instance);
-	virtual void instance_custom_data_update_gi_probes(InstanceBase *p_instance);
-	virtual void instance_custom_data_update_lightmap(InstanceBase *p_instance);
-	virtual void instance_custom_data_update_transform(InstanceBase *p_instance);
-
 	virtual bool free(RID p_rid);
 
 	RasterizerSceneForwardRD(RasterizerStorageRD *p_storage);

Разлика између датотеке није приказан због своје велике величине
+ 982 - 156
servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp


+ 329 - 29
servers/visual/rasterizer_rd/rasterizer_scene_rd.h

@@ -15,20 +15,17 @@ protected:
 	};
 	virtual RenderBufferData *_create_render_buffer_data() = 0;
 
-	virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+	virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0;
 
 private:
 	int roughness_layers;
 
 	RasterizerStorageRD *storage;
 
-	struct Sky {
-		int radiance_size = 256;
-		VS::SkyMode mode = VS::SKY_MODE_QUALITY;
-		RID panorama;
+	struct ReflectionData {
 		RID radiance;
-		bool dirty = false;
-		Sky *dirty_list = nullptr;
+
 		struct Layer {
 			struct Mipmap {
 				RID framebuffers[6];
@@ -38,9 +35,26 @@ private:
 			Vector<Mipmap> mipmaps;
 		};
 		RID radiance_base_cubemap; //cubemap for first layer, first cubemap
+
 		Vector<Layer> layers;
 	};
 
+	void _clear_reflection_data(ReflectionData &rd);
+	void _update_reflection_data(ReflectionData &rd, int p_size, bool p_quality);
+	void _create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality);
+	void _create_reflection_from_base_mipmap(ReflectionData &rd, bool p_quality, int p_cube_side);
+	void _update_reflection_mipmaps(ReflectionData &rd, bool p_quality);
+
+	/* SKY */
+	struct Sky {
+		int radiance_size = 256;
+		VS::SkyMode mode = VS::SKY_MODE_QUALITY;
+		RID panorama;
+		ReflectionData reflection;
+		bool dirty = false;
+		Sky *dirty_list = nullptr;
+	};
+
 	Sky *dirty_sky_list = nullptr;
 
 	void _sky_invalidate(Sky *p_sky);
@@ -52,6 +66,156 @@ private:
 
 	mutable RID_Owner<Sky> sky_owner;
 
+	/* REFLECTION PROBE INSTANCE */
+
+	struct ReflectionProbeInstance {
+
+		RID probe;
+
+		ReflectionData reflection;
+		RID depth_buffer;
+		RID render_fb[6];
+
+		int current_resolution = 0;
+
+		bool dirty = true;
+		bool rendering = false;
+		int processing_side = 0;
+
+		uint32_t render_index = 0;
+
+		Transform transform;
+	};
+
+	mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
+
+	/* SHADOW ATLAS */
+
+	struct ShadowAtlas {
+
+		enum {
+			QUADRANT_SHIFT = 27,
+			SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1,
+			SHADOW_INVALID = 0xFFFFFFFF
+		};
+
+		struct Quadrant {
+
+			uint32_t subdivision;
+
+			struct Shadow {
+				RID owner;
+				uint64_t version;
+				uint64_t alloc_tick;
+
+				Shadow() {
+					version = 0;
+					alloc_tick = 0;
+				}
+			};
+
+			Vector<Shadow> shadows;
+
+			Quadrant() {
+				subdivision = 0; //not in use
+			}
+
+		} quadrants[4];
+
+		int size_order[4] = { 0, 1, 2, 3 };
+		uint32_t smallest_subdiv = 0;
+
+		int size = 0;
+
+		RID depth;
+		RID fb; //for copying
+
+		Map<RID, uint32_t> shadow_owners;
+	};
+
+	RID_Owner<ShadowAtlas> shadow_atlas_owner;
+
+	bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
+
+	/* DIRECTIONAL SHADOW */
+
+	struct DirectionalShadow {
+		RID depth;
+		RID fb; //for copying
+
+		int light_count = 0;
+		int size = 0;
+		int current_light = 0;
+	} directional_shadow;
+
+	/* SHADOW CUBEMAPS */
+
+	struct ShadowCubemap {
+
+		RID cubemap;
+		RID side_fb[6];
+	};
+
+	Map<int, ShadowCubemap> shadow_cubemaps;
+	ShadowCubemap *_get_shadow_cubemap(int p_size);
+
+	struct ShadowMap {
+		RID depth;
+		RID fb;
+	};
+
+	Map<Vector2i, ShadowMap> shadow_maps;
+	ShadowMap *_get_shadow_map(const Size2i &p_size);
+
+	void _create_shadow_cubemaps();
+
+	/* LIGHT INSTANCE */
+
+	struct LightInstance {
+
+		struct ShadowTransform {
+
+			CameraMatrix camera;
+			Transform transform;
+			float farplane;
+			float split;
+			float bias_scale;
+		};
+
+		VS::LightType light_type;
+
+		ShadowTransform shadow_transform[4];
+
+		RID self;
+		RID light;
+		Transform transform;
+
+		Vector3 light_vector;
+		Vector3 spot_vector;
+		float linear_att;
+
+		uint64_t shadow_pass = 0;
+		uint64_t last_scene_pass = 0;
+		uint64_t last_scene_shadow_pass = 0;
+		uint64_t last_pass = 0;
+		uint32_t light_index = 0;
+		uint32_t light_directional_index = 0;
+
+		uint32_t current_shadow_atlas_key;
+
+		Vector2 dp;
+
+		Rect2 directional_rect;
+
+		Set<RID> shadow_atlases; //shadow atlases where this light is registered
+
+		LightInstance() {}
+	};
+
+	mutable RID_Owner<LightInstance> light_instance_owner;
+
+	/* ENVIRONMENT */
+
 	struct Environent {
 
 		// BG
@@ -82,6 +246,8 @@ private:
 
 	mutable RID_Owner<Environent> environment_owner;
 
+	/* RENDER BUFFERS */
+
 	struct RenderBuffers {
 
 		RenderBufferData *data = nullptr;
@@ -92,16 +258,45 @@ private:
 
 	mutable RID_Owner<RenderBuffers> render_buffers_owner;
 
+	uint64_t scene_pass = 0;
+	uint64_t shadow_atlas_realloc_tolerance_msec = 500;
+
 public:
 	/* SHADOW ATLAS API */
 
-	RID shadow_atlas_create() { return RID(); }
-	void shadow_atlas_set_size(RID p_atlas, int p_size) {}
-	void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {}
-	bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { return false; }
-
-	int get_directional_light_shadow_size(RID p_light_intance) { return 0; }
-	void set_directional_shadow_count(int p_count) {}
+	RID shadow_atlas_create();
+	void shadow_atlas_set_size(RID p_atlas, int p_size);
+	void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
+	bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
+	_FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
+		ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+		ERR_FAIL_COND_V(!atlas, false);
+		return atlas->shadow_owners.has(p_light_intance);
+	}
+
+	_FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) {
+		ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+		ERR_FAIL_COND_V(!atlas, RID());
+		return atlas->depth;
+	}
+
+	_FORCE_INLINE_ Size2i shadow_atlas_get_size(RID p_atlas) {
+		ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+		ERR_FAIL_COND_V(!atlas, Size2i());
+		return Size2(atlas->size, atlas->size);
+	}
+
+	void directional_shadow_atlas_set_size(int p_size);
+	int get_directional_light_shadow_size(RID p_light_intance);
+	void set_directional_shadow_count(int p_count);
+
+	_FORCE_INLINE_ RID directional_shadow_get_texture() {
+		return directional_shadow.depth;
+	}
+
+	_FORCE_INLINE_ Size2i directional_shadow_get_size() {
+		return Size2i(directional_shadow.size, directional_shadow.size);
+	}
 
 	/* SKY API */
 
@@ -166,22 +361,121 @@ public:
 	void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {}
 	void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {}
 
-	RID light_instance_create(RID p_light) { return RID(); }
-	void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {}
-	void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) {}
-	void light_instance_mark_visible(RID p_light_instance) {}
+	RID light_instance_create(RID p_light);
+	void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
+	void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
+	void light_instance_mark_visible(RID p_light_instance);
+
+	_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->light;
+	}
+
+	_FORCE_INLINE_ Transform light_instance_get_base_transform(RID p_light_instance) {
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->transform;
+	}
 
-	RID reflection_atlas_create() { return RID(); }
-	void reflection_atlas_set_size(RID p_ref_atlas, int p_size) {}
-	void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) {}
+	_FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas) {
 
-	RID reflection_probe_instance_create(RID p_probe) { return RID(); }
-	void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {}
-	void reflection_probe_release_atlas_index(RID p_instance) {}
-	bool reflection_probe_instance_needs_redraw(RID p_instance) { return false; }
-	bool reflection_probe_instance_has_reflection(RID p_instance) { return false; }
-	bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { return false; }
-	bool reflection_probe_instance_postprocess_step(RID p_instance) { return true; }
+		ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		uint32_t key = shadow_atlas->shadow_owners[li->self];
+
+		uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
+		uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+		ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2());
+
+		uint32_t atlas_size = shadow_atlas->size;
+		uint32_t quadrant_size = atlas_size >> 1;
+
+		uint32_t x = (quadrant & 1) * quadrant_size;
+		uint32_t y = (quadrant >> 1) * quadrant_size;
+
+		uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+		x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+		y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+
+		uint32_t width = shadow_size;
+		uint32_t height = shadow_size;
+
+		return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size));
+	}
+
+	_FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
+
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->shadow_transform[p_index].camera;
+	}
+
+	_FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		li->last_pass = p_pass;
+	}
+
+	_FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) {
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->last_pass;
+	}
+
+	_FORCE_INLINE_ void light_instance_set_index(RID p_light_instance, uint32_t p_index) {
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		li->light_index = p_index;
+	}
+
+	_FORCE_INLINE_ uint32_t light_instance_get_index(RID p_light_instance) {
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->light_index;
+	}
+
+	_FORCE_INLINE_ VS::LightType light_instance_get_type(RID p_light_instance) {
+		LightInstance *li = light_instance_owner.getornull(p_light_instance);
+		return li->light_type;
+	}
+
+	virtual RID reflection_probe_instance_create(RID p_probe);
+	virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
+	virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
+	virtual void reflection_probe_instance_begin_render(RID p_instance);
+	virtual bool reflection_probe_instance_postprocess_step(RID p_instance);
+
+	uint32_t reflection_probe_instance_get_resolution(RID p_instance);
+	RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index);
+
+	_FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) {
+		ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+		ERR_FAIL_COND_V(!rpi, RID());
+
+		return rpi->probe;
+	}
+
+	_FORCE_INLINE_ void reflection_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) {
+		ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+		ERR_FAIL_COND(!rpi);
+		rpi->render_index = p_render_index;
+	}
+
+	_FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_index(RID p_instance) {
+		ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+		ERR_FAIL_COND_V(!rpi, 0);
+
+		return rpi->render_index;
+	}
+
+	_FORCE_INLINE_ Transform reflection_probe_instance_get_transform(RID p_instance) {
+		ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+		ERR_FAIL_COND_V(!rpi, Transform());
+
+		return rpi->transform;
+	}
+
+	_FORCE_INLINE_ RID reflection_probe_instance_get_texture(RID p_instance) {
+		ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+		ERR_FAIL_COND_V(!rpi, RID());
+
+		return rpi->reflection.radiance;
+	}
 
 	RID gi_probe_instance_create() { return RID(); }
 	void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {}
@@ -191,7 +485,12 @@ public:
 	RID render_buffers_create();
 	void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
 
-	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+
+	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
+
+	virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; }
+	_FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; }
 
 	int get_roughness_layers() const;
 	bool is_using_radiance_cubemap_array() const;
@@ -201,6 +500,7 @@ public:
 	virtual void update();
 
 	RasterizerSceneRD(RasterizerStorageRD *p_storage);
+	~RasterizerSceneRD();
 };
 
 #endif // RASTERIZER_SCENE_RD_H

+ 490 - 30
servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp

@@ -2087,6 +2087,462 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
 	v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
 }
 
+/* LIGHT */
+
+RID RasterizerStorageRD::light_create(VS::LightType p_type) {
+
+	Light light;
+	light.type = p_type;
+
+	light.param[VS::LIGHT_PARAM_ENERGY] = 1.0;
+	light.param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+	light.param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
+	light.param[VS::LIGHT_PARAM_RANGE] = 1.0;
+	light.param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
+	light.param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45;
+	light.param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
+	light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
+	light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
+	light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
+	light.param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
+	light.param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
+
+	return light_owner.make_rid(light);
+}
+
+void RasterizerStorageRD::light_set_color(RID p_light, const Color &p_color) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->color = p_color;
+}
+void RasterizerStorageRD::light_set_param(RID p_light, VS::LightParam p_param, float p_value) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+	ERR_FAIL_INDEX(p_param, VS::LIGHT_PARAM_MAX);
+
+	switch (p_param) {
+		case VS::LIGHT_PARAM_RANGE:
+		case VS::LIGHT_PARAM_SPOT_ANGLE:
+		case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
+		case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
+		case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
+		case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
+		case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
+		case VS::LIGHT_PARAM_SHADOW_BIAS: {
+
+			light->version++;
+			light->instance_dependency.instance_notify_changed(true, false);
+		} break;
+		default: {
+		}
+	}
+
+	light->param[p_param] = p_value;
+}
+void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+	light->shadow = p_enabled;
+
+	light->version++;
+	light->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+	light->shadow_color = p_color;
+}
+
+void RasterizerStorageRD::light_set_projector(RID p_light, RID p_texture) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->projector = p_texture;
+}
+
+void RasterizerStorageRD::light_set_negative(RID p_light, bool p_enable) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->negative = p_enable;
+}
+void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->cull_mask = p_mask;
+
+	light->version++;
+	light->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->reverse_cull = p_enabled;
+
+	light->version++;
+	light->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::light_set_use_gi(RID p_light, bool p_enabled) {
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->use_gi = p_enabled;
+
+	light->version++;
+	light->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->omni_shadow_mode = p_mode;
+
+	light->version++;
+	light->instance_dependency.instance_notify_changed(true, false);
+}
+
+VS::LightOmniShadowMode RasterizerStorageRD::light_omni_get_shadow_mode(RID p_light) {
+
+	const Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI_SHADOW_CUBE);
+
+	return light->omni_shadow_mode;
+}
+
+void RasterizerStorageRD::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->directional_shadow_mode = p_mode;
+	light->version++;
+	light->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->directional_blend_splits = p_enable;
+	light->version++;
+	light->instance_dependency.instance_notify_changed(true, false);
+}
+
+bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const {
+
+	const Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND_V(!light, false);
+
+	return light->directional_blend_splits;
+}
+
+VS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) {
+
+	const Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
+
+	return light->directional_shadow_mode;
+}
+
+void RasterizerStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->directional_range_mode = p_range_mode;
+}
+
+VS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const {
+
+	const Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
+
+	return light->directional_range_mode;
+}
+
+bool RasterizerStorageRD::light_get_use_gi(RID p_light) {
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND_V(!light, false);
+
+	return light->use_gi;
+}
+
+uint64_t RasterizerStorageRD::light_get_version(RID p_light) const {
+
+	const Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND_V(!light, 0);
+
+	return light->version;
+}
+
+AABB RasterizerStorageRD::light_get_aabb(RID p_light) const {
+
+	const Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND_V(!light, AABB());
+
+	switch (light->type) {
+
+		case VS::LIGHT_SPOT: {
+
+			float len = light->param[VS::LIGHT_PARAM_RANGE];
+			float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len;
+			return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
+		};
+		case VS::LIGHT_OMNI: {
+
+			float r = light->param[VS::LIGHT_PARAM_RANGE];
+			return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
+		};
+		case VS::LIGHT_DIRECTIONAL: {
+
+			return AABB();
+		};
+	}
+
+	ERR_FAIL_V(AABB());
+}
+
+/* REFLECTION PROBE */
+
+RID RasterizerStorageRD::reflection_probe_create() {
+
+	return reflection_probe_owner.make_rid(ReflectionProbe());
+}
+
+void RasterizerStorageRD::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->update_mode = p_mode;
+	reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->intensity = p_intensity;
+}
+
+void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->interior_ambient = p_ambient;
+}
+
+void RasterizerStorageRD::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->interior_ambient_energy = p_energy;
+}
+
+void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->interior_ambient_probe_contrib = p_contrib;
+}
+
+void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->max_distance = p_distance;
+
+	reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->extents = p_extents;
+	reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->origin_offset = p_offset;
+	reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->interior = p_enable;
+	reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->box_projection = p_enable;
+}
+
+void RasterizerStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->enable_shadows = p_enable;
+	reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+
+	reflection_probe->cull_mask = p_layers;
+	reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+
+	ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND(!reflection_probe);
+	ERR_FAIL_COND(p_resolution < 32);
+
+	reflection_probe->resolution = p_resolution;
+}
+
+AABB RasterizerStorageRD::reflection_probe_get_aabb(RID p_probe) const {
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, AABB());
+
+	AABB aabb;
+	aabb.position = -reflection_probe->extents;
+	aabb.size = reflection_probe->extents * 2.0;
+
+	return aabb;
+}
+VS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_mode(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS);
+
+	return reflection_probe->update_mode;
+}
+
+uint32_t RasterizerStorageRD::reflection_probe_get_cull_mask(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->cull_mask;
+}
+
+Vector3 RasterizerStorageRD::reflection_probe_get_extents(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+	return reflection_probe->extents;
+}
+Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+	return reflection_probe->origin_offset;
+}
+
+bool RasterizerStorageRD::reflection_probe_renders_shadows(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, false);
+
+	return reflection_probe->enable_shadows;
+}
+
+float RasterizerStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->max_distance;
+}
+
+int RasterizerStorageRD::reflection_probe_get_resolution(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->resolution;
+}
+
+float RasterizerStorageRD::reflection_probe_get_intensity(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->intensity;
+}
+bool RasterizerStorageRD::reflection_probe_is_interior(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, false);
+
+	return reflection_probe->interior;
+}
+bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, false);
+
+	return reflection_probe->box_projection;
+}
+
+Color RasterizerStorageRD::reflection_probe_get_interior_ambient(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, Color());
+
+	return reflection_probe->interior_ambient;
+}
+float RasterizerStorageRD::reflection_probe_get_interior_ambient_energy(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->interior_ambient_energy;
+}
+float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const {
+
+	const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+	ERR_FAIL_COND_V(!reflection_probe, 0);
+
+	return reflection_probe->interior_ambient_probe_contrib;
+}
+
 /* RENDER TARGET API */
 
 void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
@@ -2432,6 +2888,12 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
 	if (mesh_owner.owns(p_base)) {
 		Mesh *mesh = mesh_owner.getornull(p_base);
 		p_instance->update_dependency(&mesh->instance_dependency);
+	} else if (reflection_probe_owner.owns(p_base)) {
+		ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
+		p_instance->update_dependency(&rp->instance_dependency);
+	} else if (light_owner.owns(p_base)) {
+		Light *l = light_owner.getornull(p_base);
+		p_instance->update_dependency(&l->instance_dependency);
 	}
 }
 
@@ -2440,6 +2902,13 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
 	if (mesh_owner.owns(p_rid)) {
 		return VS::INSTANCE_MESH;
 	}
+	if (reflection_probe_owner.owns(p_rid)) {
+		return VS::INSTANCE_REFLECTION_PROBE;
+	}
+	if (light_owner.owns(p_rid)) {
+		return VS::INSTANCE_LIGHT;
+	}
+
 	return VS::INSTANCE_NONE;
 }
 void RasterizerStorageRD::update_dirty_resources() {
@@ -2461,6 +2930,13 @@ bool RasterizerStorageRD::free(RID p_rid) {
 			RD::get_singleton()->free(t->rd_texture);
 		}
 
+		if (t->is_proxy && t->proxy_to.is_valid()) {
+			Texture *proxy_to = texture_owner.getornull(t->proxy_to);
+			if (proxy_to) {
+				proxy_to->proxies.erase(p_rid);
+			}
+		}
+
 		for (int i = 0; i < t->proxies.size(); i++) {
 			Texture *p = texture_owner.getornull(t->proxies[i]);
 			ERR_CONTINUE(!p);
@@ -2495,6 +2971,18 @@ bool RasterizerStorageRD::free(RID p_rid) {
 		Mesh *mesh = mesh_owner.getornull(p_rid);
 		mesh->instance_dependency.instance_notify_deleted(p_rid);
 		mesh_owner.free(p_rid);
+	} else if (reflection_probe_owner.owns(p_rid)) {
+		ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
+		reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
+		reflection_probe_owner.free(p_rid);
+
+	} else if (light_owner.owns(p_rid)) {
+
+		// delete the texture
+		Light *light = light_owner.getornull(p_rid);
+		light->instance_dependency.instance_notify_deleted(p_rid);
+		light_owner.free(p_rid);
+
 	} else if (render_target_owner.owns(p_rid)) {
 		RenderTarget *rt = render_target_owner.getornull(p_rid);
 
@@ -2606,7 +3094,7 @@ RasterizerStorageRD::RasterizerStorageRD() {
 		tformat.height = 4;
 		tformat.array_layers = 6;
 		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
-		tformat.type = RD::TEXTURE_TYPE_CUBE;
+		tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
 
 		PoolVector<uint8_t> pv;
 		pv.resize(16 * 4);
@@ -2634,7 +3122,7 @@ RasterizerStorageRD::RasterizerStorageRD() {
 		tformat.height = 4;
 		tformat.array_layers = 6;
 		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
-		tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+		tformat.type = RD::TEXTURE_TYPE_CUBE;
 
 		PoolVector<uint8_t> pv;
 		pv.resize(16 * 4);
@@ -2680,34 +3168,6 @@ RasterizerStorageRD::RasterizerStorageRD() {
 		}
 	}
 
-	{ //create default cubemap array
-
-		RD::TextureFormat tformat;
-		tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
-		tformat.width = 4;
-		tformat.height = 4;
-		tformat.array_layers = 6;
-		tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
-		tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
-
-		PoolVector<uint8_t> pv;
-		pv.resize(16 * 4);
-		for (int i = 0; i < 16; i++) {
-			pv.set(i * 4 + 0, 0);
-			pv.set(i * 4 + 1, 0);
-			pv.set(i * 4 + 2, 0);
-			pv.set(i * 4 + 3, 0);
-		}
-
-		{
-			Vector<PoolVector<uint8_t> > vpv;
-			for (int i = 0; i < 6; i++) {
-				vpv.push_back(pv);
-			}
-			default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
-		}
-	}
-
 	//default samplers
 	for (int i = 1; i < VS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
 		for (int j = 1; j < VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {

+ 191 - 54
servers/visual/rasterizer_rd/rasterizer_storage_rd.h

@@ -251,6 +251,12 @@ private:
 			RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed
 
 			RID material;
+
+			uint32_t render_index = 0;
+			uint64_t render_pass = 0;
+
+			uint32_t multimesh_render_index = 0;
+			uint64_t multimesh_render_pass = 0;
 		};
 
 		uint32_t blend_shape_count = 0;
@@ -275,6 +281,54 @@ private:
 
 	RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
 
+	/* LIGHT */
+
+	struct Light {
+
+		VS::LightType type;
+		float param[VS::LIGHT_PARAM_MAX];
+		Color color = Color(1, 1, 1, 1);
+		Color shadow_color;
+		RID projector;
+		bool shadow = false;
+		bool negative = false;
+		bool reverse_cull = false;
+		bool use_gi = true;
+		uint32_t cull_mask = 0xFFFFFFFF;
+		VS::LightOmniShadowMode omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+		VS::LightDirectionalShadowMode directional_shadow_mode = VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+		VS::LightDirectionalShadowDepthRangeMode directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
+		bool directional_blend_splits = false;
+		uint64_t version = 0;
+
+		RasterizerScene::InstanceDependency instance_dependency;
+	};
+
+	mutable RID_Owner<Light> light_owner;
+
+	/* REFLECTION PROBE */
+
+	struct ReflectionProbe {
+
+		VS::ReflectionProbeUpdateMode update_mode = VS::REFLECTION_PROBE_UPDATE_ONCE;
+		int resolution = 256;
+		float intensity = 1.0;
+		Color interior_ambient;
+		float interior_ambient_energy = 1.0;
+		float interior_ambient_probe_contrib = 0.0;
+		float max_distance = 0;
+		Vector3 extents = Vector3(1, 1, 1);
+		Vector3 origin_offset;
+		bool interior = false;
+		bool box_projection = false;
+		bool enable_shadows = false;
+		uint32_t cull_mask = (1 << 20) - 1;
+
+		RasterizerScene::InstanceDependency instance_dependency;
+	};
+
+	mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
+
 	/* RENDER TARGET */
 
 	struct RenderTarget {
@@ -530,6 +584,32 @@ public:
 		return mesh_default_rd_buffers[p_buffer];
 	}
 
+	_FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+		Mesh *mesh = mesh_owner.getornull(p_mesh);
+		Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+		if (s->render_pass != p_render_pass) {
+			(*r_index)++;
+			s->render_pass = p_render_pass;
+			s->render_index = *r_index;
+		}
+
+		return s->render_index;
+	}
+
+	_FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+		Mesh *mesh = mesh_owner.getornull(p_mesh);
+		Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+		if (s->multimesh_render_pass != p_render_pass) {
+			(*r_index)++;
+			s->multimesh_render_pass = p_render_pass;
+			s->multimesh_render_index = *r_index;
+		}
+
+		return s->multimesh_render_index;
+	}
+
 	/* MULTIMESH API */
 
 	virtual RID multimesh_create() { return RID(); }
@@ -587,68 +667,125 @@ public:
 
 	/* Light API */
 
-	RID light_create(VS::LightType p_type) { return RID(); }
+	RID light_create(VS::LightType p_type);
 
 	RID directional_light_create() { return light_create(VS::LIGHT_DIRECTIONAL); }
 	RID omni_light_create() { return light_create(VS::LIGHT_OMNI); }
 	RID spot_light_create() { return light_create(VS::LIGHT_SPOT); }
 
-	void light_set_color(RID p_light, const Color &p_color) {}
-	void light_set_param(RID p_light, VS::LightParam p_param, float p_value) {}
-	void light_set_shadow(RID p_light, bool p_enabled) {}
-	void light_set_shadow_color(RID p_light, const Color &p_color) {}
-	void light_set_projector(RID p_light, RID p_texture) {}
-	void light_set_negative(RID p_light, bool p_enable) {}
-	void light_set_cull_mask(RID p_light, uint32_t p_mask) {}
-	void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {}
-	void light_set_use_gi(RID p_light, bool p_enabled) {}
-
-	void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {}
-	void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) {}
-
-	void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) {}
-	void light_directional_set_blend_splits(RID p_light, bool p_enable) {}
-	bool light_directional_get_blend_splits(RID p_light) const { return false; }
-	void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {}
-	VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const { return VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; }
-
-	VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) { return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
-	VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) { return VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
-
-	bool light_has_shadow(RID p_light) const { return false; }
-
-	VS::LightType light_get_type(RID p_light) const { return VS::LIGHT_OMNI; }
-	AABB light_get_aabb(RID p_light) const { return AABB(); }
-	float light_get_param(RID p_light, VS::LightParam p_param) { return 0.0; }
-	Color light_get_color(RID p_light) { return Color(); }
-	bool light_get_use_gi(RID p_light) { return false; }
-	uint64_t light_get_version(RID p_light) const { return 0; }
+	void light_set_color(RID p_light, const Color &p_color);
+	void light_set_param(RID p_light, VS::LightParam p_param, float p_value);
+	void light_set_shadow(RID p_light, bool p_enabled);
+	void light_set_shadow_color(RID p_light, const Color &p_color);
+	void light_set_projector(RID p_light, RID p_texture);
+	void light_set_negative(RID p_light, bool p_enable);
+	void light_set_cull_mask(RID p_light, uint32_t p_mask);
+	void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
+	void light_set_use_gi(RID p_light, bool p_enabled);
+
+	void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode);
+
+	void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode);
+	void light_directional_set_blend_splits(RID p_light, bool p_enable);
+	bool light_directional_get_blend_splits(RID p_light) const;
+	void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode);
+	VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
+
+	VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
+	VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
+
+	_FORCE_INLINE_ VS::LightType light_get_type(RID p_light) const {
+		const Light *light = light_owner.getornull(p_light);
+		ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
+
+		return light->type;
+	}
+	AABB light_get_aabb(RID p_light) const;
+
+	_FORCE_INLINE_ float light_get_param(RID p_light, VS::LightParam p_param) {
+
+		const Light *light = light_owner.getornull(p_light);
+		ERR_FAIL_COND_V(!light, 0);
+
+		return light->param[p_param];
+	}
+
+	_FORCE_INLINE_ Color light_get_color(RID p_light) {
+
+		const Light *light = light_owner.getornull(p_light);
+		ERR_FAIL_COND_V(!light, Color());
+
+		return light->color;
+	}
+
+	_FORCE_INLINE_ Color light_get_shadow_color(RID p_light) {
+
+		const Light *light = light_owner.getornull(p_light);
+		ERR_FAIL_COND_V(!light, Color());
+
+		return light->shadow_color;
+	}
+
+	_FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
+
+		const Light *light = light_owner.getornull(p_light);
+		ERR_FAIL_COND_V(!light, 0);
+
+		return light->cull_mask;
+	}
+
+	_FORCE_INLINE_ bool light_has_shadow(RID p_light) const {
+
+		const Light *light = light_owner.getornull(p_light);
+		ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
+
+		return light->shadow;
+	}
+
+	_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
+
+		const Light *light = light_owner.getornull(p_light);
+		ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
+
+		return light->negative;
+	}
+
+	bool light_get_use_gi(RID p_light);
+	uint64_t light_get_version(RID p_light) const;
 
 	/* PROBE API */
 
-	RID reflection_probe_create() { return RID(); }
-
-	void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {}
-	void reflection_probe_set_intensity(RID p_probe, float p_intensity) {}
-	void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {}
-	void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {}
-	void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {}
-	void reflection_probe_set_max_distance(RID p_probe, float p_distance) {}
-	void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {}
-	void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {}
-	void reflection_probe_set_as_interior(RID p_probe, bool p_enable) {}
-	void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {}
-	void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {}
-	void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {}
-	void reflection_probe_set_resolution(RID p_probe, int p_resolution) {}
-
-	AABB reflection_probe_get_aabb(RID p_probe) const { return AABB(); }
-	VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const { return VisualServer::REFLECTION_PROBE_UPDATE_ONCE; }
-	uint32_t reflection_probe_get_cull_mask(RID p_probe) const { return 0; }
-	Vector3 reflection_probe_get_extents(RID p_probe) const { return Vector3(); }
-	Vector3 reflection_probe_get_origin_offset(RID p_probe) const { return Vector3(); }
-	float reflection_probe_get_origin_max_distance(RID p_probe) const { return 0.0; }
-	bool reflection_probe_renders_shadows(RID p_probe) const { return false; }
+	RID reflection_probe_create();
+
+	void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode);
+	void reflection_probe_set_intensity(RID p_probe, float p_intensity);
+	void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient);
+	void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy);
+	void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib);
+	void reflection_probe_set_max_distance(RID p_probe, float p_distance);
+	void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents);
+	void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset);
+	void reflection_probe_set_as_interior(RID p_probe, bool p_enable);
+	void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
+	void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
+	void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
+	void reflection_probe_set_resolution(RID p_probe, int p_resolution);
+
+	AABB reflection_probe_get_aabb(RID p_probe) const;
+	VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
+	uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
+	Vector3 reflection_probe_get_extents(RID p_probe) const;
+	Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
+	float reflection_probe_get_origin_max_distance(RID p_probe) const;
+	int reflection_probe_get_resolution(RID p_probe) const;
+	bool reflection_probe_renders_shadows(RID p_probe) const;
+
+	float reflection_probe_get_intensity(RID p_probe) const;
+	bool reflection_probe_is_interior(RID p_probe) const;
+	bool reflection_probe_is_box_projection(RID p_probe) const;
+	Color reflection_probe_get_interior_ambient(RID p_probe) const;
+	float reflection_probe_get_interior_ambient_energy(RID p_probe) const;
+	float reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const;
 
 	void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
 	void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {}

+ 12 - 2
servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h

@@ -31,10 +31,13 @@
 #ifndef RENDER_PIPELINE_CACHE_RD_H
 #define RENDER_PIPELINE_CACHE_RD_H
 
+#include "core/spin_lock.h"
 #include "servers/visual/rendering_device.h"
 
 class RenderPipelineVertexFormatCacheRD {
 
+	SpinLock spin_lock;
+
 	RID shader;
 	uint32_t input_mask;
 
@@ -68,12 +71,19 @@ public:
 		ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
 				"Attempted to use an unused shader variant (shader is null),");
 #endif
+
+		spin_lock.lock();
+		RID result;
 		for (uint32_t i = 0; i < version_count; i++) {
 			if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) {
-				return versions[i].pipeline;
+				result = versions[i].pipeline;
+				spin_lock.unlock();
+				return result;
 			}
 		}
-		return _generate_version(p_vertex_format_id, p_framebuffer_format_id);
+		result = _generate_version(p_vertex_format_id, p_framebuffer_format_id);
+		spin_lock.unlock();
+		return result;
 	}
 
 	_FORCE_INLINE_ uint32_t get_vertex_input_mask() const {

+ 1 - 0
servers/visual/rasterizer_rd/shaders/SCsub

@@ -10,4 +10,5 @@ if 'RD_GLSL' in env['BUILDERS']:
     env.RD_GLSL('scene_forward.glsl');
     env.RD_GLSL('sky.glsl');
     env.RD_GLSL('tonemap.glsl');
+    env.RD_GLSL('copy.glsl');
 

+ 4 - 0
servers/visual/rasterizer_rd/shaders/blur.glsl

@@ -23,6 +23,10 @@ void main() {
 
 	gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
 
+	if (bool(blur.flags&FLAG_FLIP_Y)) {
+		uv_interp.y = 1.0 - uv_interp.y;
+	}
+
 }
 
 /* clang-format off */

+ 1 - 0
servers/visual/rasterizer_rd/shaders/blur_inc.glsl

@@ -3,6 +3,7 @@
 #define FLAG_USE_ORTHOGONAL_PROJECTION (1<<2)
 #define FLAG_DOF_NEAR_FIRST_TAP (1<<3)
 #define FLAG_GLOW_FIRST_PASS (1<<4)
+#define FLAG_FLIP_Y (1<<5)
 
 layout(push_constant, binding = 1, std430) uniform Blur {
 	vec4 section;

+ 93 - 0
servers/visual/rasterizer_rd/shaders/copy.glsl

@@ -0,0 +1,93 @@
+/* clang-format off */
+[vertex]
+/* clang-format on */
+
+#version 450
+
+/* clang-format off */
+VERSION_DEFINES
+/* clang-format on */
+
+layout(location =0) out vec2 uv_interp;
+
+void main() {
+
+	vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));
+	uv_interp = base_arr[gl_VertexIndex];
+
+	gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
+
+}
+
+/* clang-format off */
+[fragment]
+/* clang-format on */
+
+#version 450
+
+/* clang-format off */
+VERSION_DEFINES
+/* clang-format on */
+
+layout(location =0) in vec2 uv_interp;
+
+#ifdef MODE_CUBE_TO_DP
+
+layout( set=0, binding=0 ) uniform samplerCube source_cube;
+
+layout(push_constant, binding = 0, std430) uniform Params {
+	float bias;
+	float z_far;
+	float z_near;
+	bool z_flip;
+
+} params;
+
+layout(location=0) out float depth_buffer;
+
+#endif
+
+
+void main() {
+
+#ifdef MODE_CUBE_TO_DP
+
+	vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
+
+	normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
+	normal = normalize(normal);
+
+
+	normal.y = -normal.y; //needs to be flipped to match projection matrix
+	if (!params.z_flip) {
+		normal.z = -normal.z;
+	}
+
+	float depth = texture(source_cube, normal).r;
+
+	// absolute values for direction cosines, bigger value equals closer to basis axis
+	vec3 unorm = abs(normal);
+
+	if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
+		// x code
+		unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
+	} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
+		// y code
+		unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
+	} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
+		// z code
+		unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+	} else {
+		// oh-no we messed up code
+		// has to be
+		unorm = vec3(1.0, 0.0, 0.0);
+	}
+
+	float depth_fix = 1.0 / dot(normal, unorm);
+
+	depth = 2.0 * depth - 1.0;
+	float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+	depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
+
+#endif
+}

+ 491 - 12
servers/visual/rasterizer_rd/shaders/scene_forward.glsl

@@ -75,12 +75,26 @@ VERTEX_SHADER_GLOBALS
 // See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
 //invariant gl_Position;
 
+layout(location =7) flat out uint instance_index;
+
+#ifdef MODE_DUAL_PARABOLOID
+
+layout(location =8) out float dp_clip;
+
+#endif
+
 void main() {
 
+	instance_index = draw_call.instance_index;
+
+	/*if (draw_call.instance_increment) {
+		instance_index += gl_InstanceIndex;
+	}*/
+
 	vec3 vertex = vertex_attrib;
 
-	mat4 world_matrix = instance_data.transform;
-	mat3 world_normal_matrix= instance_data.normal_transform;
+	mat4 world_matrix = instances.data[instance_index].transform;
+	mat3 world_normal_matrix= mat3(instances.data[instance_index].normal_transform);
 
 	vec3 normal = normal_attrib;
 
@@ -131,8 +145,8 @@ void main() {
 
 	float roughness = 1.0;
 
-	mat4 modelview = scene_data.inv_camera_matrix * instance_data.transform;
-	mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * instance_data.normal_transform;
+	mat4 modelview = scene_data.inv_camera_matrix * world_matrix;
+	mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix;
 
 	{
 		/* clang-format off */
@@ -179,14 +193,35 @@ VERTEX_SHADER_CODE
 
 #ifdef MODE_RENDER_DEPTH
 
+#ifdef MODE_DUAL_PARABOLOID
+
+	vertex_interp.z *= scene_data.dual_paraboloid_side;
+	normal_interp.z *= scene_data.dual_paraboloid_side;
+
+	dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
+
+	//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
+
+	vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
+	float distance = length(vtx);
+	vtx = normalize(vtx);
+	vtx.xy /= 1.0 - vtx.z;
+	vtx.z = (distance / scene_data.z_far);
+	vtx.z = vtx.z * 2.0 - 1.0;
+
+	vertex_interp = vtx;
+#else
+
 	float z_ofs = scene_data.z_offset;
 	z_ofs += (1.0 - abs(normal_interp.z)) * scene_data.z_slope_scale;
 	vertex_interp.z -= z_ofs;
 
+#endif
+
 #endif //MODE_RENDER_DEPTH
 
 #ifdef USE_OVERRIDE_POSITION
-	gl_Position = position;
+	gl_Position = position;;
 #else
 	gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
 #endif
@@ -227,10 +262,19 @@ layout(location = 5) in vec3 tangent_interp;
 layout(location = 6) in vec3 binormal_interp;
 #endif
 
+layout(location =7) flat in uint instance_index;
+
+#ifdef MODE_DUAL_PARABOLOID
+
+layout(location =8) in float dp_clip;
+
+#endif
+
+
 //defines to keep compatibility with vertex
 
-#define world_matrix instance_data.transform;
-#define world_normal_matrix instance_data.normal_transform;
+#define world_matrix instances.data[instance_index].transform;
+#define world_normal_matrix instances.data[instance_index].normal_transform;
 #define projection_matrix scene_data.projection_matrix;
 
 #ifdef USE_MATERIAL_UNIFORMS
@@ -253,10 +297,14 @@ layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
 layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
 #else
 
+#ifndef MODE_RENDER_DEPTH
 layout(location = 0) out vec4 frag_color;
+#endif
 
 #endif
 
+
+
 // This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
 // We're dividing this factor off because the overall term we'll end up looks like
 // (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
@@ -329,7 +377,24 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
 	return mix(vec3(dielectric), albedo, vec3(metallic));
 }
 
-void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) {
+void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color,float roughness, float metallic, float specular,float specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+		vec3 transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+		float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+		float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+		vec3 B, vec3 T,float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+		inout float alpha,
+#endif
+		inout vec3 diffuse_light, inout vec3 specular_light
+		   ) {
 
 #if defined(USE_LIGHT_SHADER_CODE)
 	// light is written by the light shader
@@ -419,11 +484,11 @@ LIGHT_SHADER_CODE
 
 		diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
 
-#if defined(TRANSMISSION_USED)
+#if defined(LIGHT_TRANSMISSION_USED)
 		diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
 #endif
 
-#if defined(RIM_LIGHT_USED)
+#if defined(LIGHT_RIM_USED)
 		float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
 		diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
 #endif
@@ -517,9 +582,209 @@ LIGHT_SHADER_CODE
 #endif //defined(USE_LIGHT_SHADER_CODE)
 }
 
+#ifndef USE_NO_SHADOWS
+
+float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec2 pos, float depth) {
+
+#ifdef SHADOW_MODE_PCF_13
+
+	float avg = textureProj(shadow, vec4(pos, depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
+	return avg * (1.0 / 13.0);
+#endif
+
+#ifdef SHADOW_MODE_PCF_5
+
+	float avg = textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos, depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
+	avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
+	return avg * (1.0 / 5.0);
+
+#endif
+
+#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
+
+	return textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos, depth, 1.0));
+
+#endif
+}
+
+#endif //USE_NO_SHADOWS
+
+
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo,float roughness, float metallic, float specular,float p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+	vec3 transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+	float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+	float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+	vec3 binormal, vec3 tangent, float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+	inout float alpha,
+#endif
+	inout vec3 diffuse_light, inout vec3 specular_light) {
+
+	vec3 light_rel_vec = lights.data[idx].position - vertex;
+	float light_length = length(light_rel_vec);
+	float normalized_distance = light_length * lights.data[idx].inv_radius;
+	vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
+	float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
+	vec3 light_attenuation = vec3(omni_attenuation);
+	vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
+	color_specular.rgb*=attenuation_energy.y;
+
+#ifndef USE_NO_SHADOWS
+	vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
+	if (shadow_color_enabled.w > 0.5) {
+		// there is a shadowmap
+
+		vec3 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
+		float shadow_len = length(splane);
+		splane = normalize(splane);
+		vec4 clamp_rect = lights.data[idx].atlas_rect;
+
+		if (splane.z >= 0.0) {
+
+			splane.z += 1.0;
+
+			clamp_rect.y += clamp_rect.w;
+
+		} else {
+
+			splane.z = 1.0 - splane.z;
+
+		}
+
+		splane.xy /= splane.z;
+		splane.xy = splane.xy * 0.5 + 0.5;
+		splane.z = shadow_len * lights.data[idx].inv_radius;
+
+		splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
+
+		light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+	}
+#endif //USE_NO_SHADOWS
+
+	light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular,color_specular.a * p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+		transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+		rim * omni_attenuation, rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+		clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+		binormal, tangent, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+		alpha
+#endif
+		diffuse_light, specular_light);
+}
+
+
+
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo,float roughness, float metallic, float specular,float p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+	vec3 transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+	float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+	float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+	vec3 binormal, vec3 tangent, float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+	inout float alpha
+#endif
+	inout vec3 diffuse_light, inout vec3 specular_light) {
+
+	vec3 light_rel_vec = lights.data[idx].position - vertex;
+	float light_length = length(light_rel_vec);
+	float normalized_distance = light_length * lights.data[idx].inv_radius;
+	vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
+	float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x);
+	vec3 spot_dir = lights.data[idx].direction;
+	vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle);
+	float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
+	float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
+	spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
+	vec3 light_attenuation = vec3(spot_attenuation);
+	vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
+	color_specular.rgb*=attenuation_energy.y;
+
+
+
+/*
+	if (lights.data[idx].atlas_rect!=vec4(0.0)) {
+		//use projector texture
+	}
+	*/
+#ifndef USE_NO_SHADOWS
+	vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
+	if (shadow_color_enabled.w > 0.5) {
+		//there is a shadowmap
+		vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+		splane.xyz /= splane.w;
+
+		float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
+
+		light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+	}
+
+#endif //USE_NO_SHADOWS
+
+	light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular,color_specular.a * p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+		transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+		rim * omni_attenuation, rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+		clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+		binormal, tangent, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+		alpha,
+#endif
+		diffuse_light, specular_light);
+}
 
 void main() {
 
+#ifdef MODE_DUAL_PARABOLOID
+
+	if (dp_clip > 0.0)
+		discard;
+#endif
 
 	//lay out everything, whathever is unused is optimized away anyway
 	vec3 vertex = vertex_interp;
@@ -701,14 +966,149 @@ FRAGMENT_SHADER_CODE
 	specular_blob_intensity *= specular * 2.0;
 #endif
 
+#ifndef MODE_RENDER_DEPTH
 	//gi probes
 
 	//lightmap
 
 	//lightmap capture
 
-	//process reflections
+#if 0
+	{ // process reflections
+
+
+		vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
+		vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
+
+		for (uint i = 0; i < MAX_REFLECTION_PROBES; i++) {
+			if (i >= draw_data.reflection_probe_count) {
+				break;
+			}
+
+			uint ref_index;
+			if (i<4) {
+				if (i<2) {
+					ref_index=draw_data.reflection_probe_indices[0];
+				} else {
+					ref_index=draw_data.reflection_probe_indices[1];
+				}
+			} else {
+				if (i<6) {
+					ref_index=draw_data.reflection_probe_indices[2];
+				} else {
+					ref_index=draw_data.reflection_probe_indices[3];
+				}
+			}
+			ref_index>>=(i&1)*16;
+			ref_index&=0xFFFF;
+
+			vec3 box_extents = reflections.data[ref_index].box_extents.xyz;
+			vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
+
+			if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
+				continue;
+			}
+
+			vec3 ref_vec = normalize(reflect(vertex, normal));
+
+			vec3 inner_pos = abs(local_pos / box_extents);
+			float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
+			//make blend more rounded
+			blend = mix(length(inner_pos), blend, blend);
+			blend *= blend;
+			blend = max(0.0, 1.0 - blend);
+
+			if (reflections.data[ref_index].params.x > 0.0) { // compute reflection
 
+				vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
+
+				if (reflections.data[ref_index].params.w > 0.5) { //box project
+
+					vec3 nrdir = normalize(local_ref_vec);
+					vec3 rbmax = (box_extents - local_pos) / nrdir;
+					vec3 rbmin = (-box_extents - local_pos) / nrdir;
+
+					vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0)));
+
+					float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
+					vec3 posonbox = local_pos + nrdir * fa;
+					local_ref_vec = posonbox - reflections.data[ref_index].box_offset.xyz;
+				}
+
+				vec4 reflection;
+
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
+
+				float lod,layer_blend;
+				layer_blend = modf(roughness * MAX_ROUGHNESS_LOD, lod);
+				reflection.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod)).rgb;
+				reflection.rgb = mix(reflection.rgb,texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod+1)).rgb,layer_blend);
+
+#else
+				reflection.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
+
+#endif
+
+				if (reflections.data[ref_index].params.z < 0.5) {
+					reflection.rgb = mix(specular_light, reflection.rgb, blend);
+				}
+
+				reflection.rgb *= reflections.data[ref_index].params.x;
+				reflection.a = blend;
+				reflection.rgb *= reflection.a;
+
+				reflection_accum += reflection;
+			}
+
+#ifndef USE_LIGHTMAP
+			if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox
+
+				vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
+
+				vec4 ambient_out;
+
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
+				ambient_out.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, MAX_ROUGHNESS_LOD)).rgb;
+#else
+				ambient_out.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_amb_vec, MAX_ROUGHNESS_LOD).rgb;
+#endif //USE_RADIANCE_CUBEMAP_ARRAY
+
+				ambient_out.a = blend;
+				ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a);
+				if (reflections.data[ref_index].params.z < 0.5) {
+					ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
+				}
+
+				ambient_out.rgb *= ambient_out.a;
+				ambient_accum += ambient_out;
+			} else {
+
+				vec4 ambient_out;
+				ambient_out.a = blend;
+				ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
+				if (reflections.data[ref_index].params.z < 0.5) {
+					ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
+				}
+				ambient_out.rgb *= ambient_out.a;
+				ambient_accum += ambient_out;
+			}
+#endif //USE_LIGHTMAP
+
+		}
+
+		if (reflection_accum.a > 0.0) {
+			specular_light = reflection_accum.rgb / reflection_accum.a;
+		}
+
+#if !defined(USE_LIGHTMAP)
+		if (ambient_accum.a > 0.0) {
+			ambient_light = ambient_accum.rgb / ambient_accum.a;
+		}
+#endif
+
+
+	}
+#endif //0
 	{
 
 #if defined(DIFFUSE_TOON)
@@ -734,8 +1134,86 @@ FRAGMENT_SHADER_CODE
 
 	//directional light
 
+	{ //omni lights
+		uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
+		for (uint i = 0; i < omni_light_count; i++) {
+
+			uint light_index = instances.data[instance_index].omni_light_indices[i>>1];
+
+			if (bool(i&1)) {
+				light_index>>=16;
+			} else {
+				light_index&=0xFFFF;
+			}
+
+			//this is done on CPU, so no need to do it here
+			//if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
+			//	continue; //not masked
+			//}
+
+			light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular,specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+					   transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+					   rim,
+					   rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+					   clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+					   tangent, binormal, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+					   alpha,
+#endif
+					   diffuse_light, specular_light);
+		}
+
+	}
+
+	{ //spot lights
+		uint spot_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
+		for (uint i = 0; i < spot_light_count; i++) {
 
-	//process omni and spots
+			uint light_index = instances.data[instance_index].spot_light_indices[i>>1];
+
+			if (bool(i&1)) {
+				light_index>>=16;
+			} else {
+				light_index&=0xFFFF;
+			}
+
+			//this is done on CPU, so no need to do it here
+			//if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
+			//	continue; //not masked
+			//}
+
+			light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular,specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+					   transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+					   rim,
+					   rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+					   clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+					   tangent, binormal, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+					   alpha,
+#endif
+					   diffuse_light, specular_light);
+		}
+
+	}
+
+
+#endif //!MODE_RENDER_DEPTH
 
 #ifdef USE_SHADOW_TO_OPACITY
 	alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
@@ -757,6 +1235,7 @@ FRAGMENT_SHADER_CODE
 #endif // USE_SHADOW_TO_OPACITY
 
 
+
 #ifdef MODE_RENDER_DEPTH
 //nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
 #else

+ 110 - 48
servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl

@@ -2,6 +2,13 @@
 #define M_PI 3.14159265359
 #define ROUGHNESS_MAX_LOD 5
 
+layout(push_constant, binding = 0, std430) uniform DrawCall {
+	uint instance_index;
+	uint pad[3]; //16 bits minimum size
+} draw_call;
+
+
+
 /* Set 0 Scene data, screen and sources (changes the least) */
 
 layout(set=0,binding=1) uniform texture2D depth_buffer;
@@ -35,7 +42,9 @@ layout(set = 0, binding = 5) uniform textureCube radiance_cubemap;
 
 layout(set = 0, binding = 6) uniform sampler material_samplers[12];
 
-layout(set=0,binding=7,std140) uniform SceneData {
+layout(set = 0, binding = 7) uniform sampler shadow_sampler;
+
+layout(set=0,binding=8,std140) uniform SceneData {
 
 	mat4 projection_matrix;
 	mat4 inv_projection_matrix;
@@ -63,6 +72,14 @@ layout(set=0,binding=7,std140) uniform SceneData {
 
 	mat3 radiance_inverse_xform;
 
+	vec2 shadow_atlas_pixel_size;
+	vec2 directional_shadow_pixel_size;
+
+	uint directional_light_count;
+	float dual_paraboloid_side;
+	float z_far;
+	uint pad0;
+
 #if 0
 	vec4 ambient_light_color;
 	vec4 bg_color;
@@ -101,80 +118,125 @@ layout(set=0,binding=7,std140) uniform SceneData {
 #endif
 } scene_data;
 
+#define INSTANCE_FLAGS_FORWARD_MASK 3
+#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3
+#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6
+#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9
+
+
+struct InstanceData {
+	mat4 transform;
+	mat4 normal_transform;
+	uint flags;
+	uint instance_ofs; //instance_offset in instancing/skeleton buffer
+	uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
+	uint layer_mask;
+
+	uint reflection_probe_indices[4];
+	uint omni_light_indices[4];
+	uint spot_light_indices[4];
+	uint decal_indices[4];
+};
+
+
+layout(set=0,binding=9,std430)  buffer Instances {
+    InstanceData data[];
+} instances;
+
+struct ReflectionData {
+
+	vec4 box_extents;
+	vec4 box_offset;
+	vec4 params; // intensity, 0, interior , boxproject
+	vec4 ambient; // ambient color, energy
+	mat4 local_matrix; // up to here for spot and omni, rest is for directional
+	// notes: for ambientblend, use distance to edge to blend between already existing global environment
+};
+
+layout(set=0,binding=10,std140) uniform ReflectionProbeData {
+	ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
+} reflections;
+
+
+struct LightData { //this structure needs to be 128 bits
+
+	vec3 position;
+	float inv_radius;
+	vec3 direction;
+	uint attenuation_energy; //attenuation
+	uint color_specular; //rgb color, a specular (8 bit unorm)
+	uint cone_attenuation_angle; // attenuation and angle, (16bit float)
+	uint mask;
+	uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
+	vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
+	mat4 shadow_matrix;
+};
+
+layout(set=0,binding=11,std140) uniform Lights {
+	LightData data[MAX_LIGHT_DATA_STRUCTS];
+} lights;
+
+layout(set=0,binding=12) uniform texture2D shadow_atlas;
 
-#if 0
 struct DirectionalLightData {
 
-	vec4 light_pos_inv_radius;
-	vec4 light_direction_attenuation;
-	vec4 light_color_energy;
-	vec4 light_params; // cone attenuation, angle, specular, shadow enabled,
-	vec4 light_clamp;
-	vec4 shadow_color_contact;
+	vec3 direction;
+	float energy;
+	vec3 color;
+	float specular;
+	uint mask;
+	uint pad0,pad1,pad2;
+	vec3 shadow_color;
+	bool shadow_enabled;
+	vec4 shadow_atlas_rect;
+	vec4 shadow_split_offsets;
 	mat4 shadow_matrix1;
 	mat4 shadow_matrix2;
 	mat4 shadow_matrix3;
 	mat4 shadow_matrix4;
-	vec4 shadow_split_offsets;
+
 };
-#endif
 
-/* Set 1 Skeleton Data (most objects lack it, so it changes little */
+layout(set=0,binding=13,std140) uniform DirectionalLights {
+	DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
+} directional_lights;
 
-#if 0
-layout(set = 1 binding = 0, std140) uniform SkeletonData {
-	mat4 transform;
-	bool use_skeleton;
-	bool use_world_coords;
-	bool pad1;
-	bool pad2;
-} skeleton;
+layout(set=0,binding=14) uniform texture2D directional_shadow_atlas;
 
-layout(set = 1, binding = 1) uniform textureBuffer skeleton_bones;
-#endif
+/*
+layout(set=0,binding=15,std430)  buffer Skeletons {
+    vec4 data[];
+} skeletons;
+*/
 
-/* Set 2 Custom Material Data (changess less than instance) */
+/* Set 1 Instancing (Multimesh) */
 
+//layout(set = 1, binding = 0) uniform textureBuffer multimesh_transforms;
 
-/* Set 3 Instance Data (Set on every draw call) */
+/* Set 2 Instancing (Multimesh) data */
 
-layout(push_constant, binding = 0, std430) uniform DrawData {
-	//used in forward rendering, 16 bits indices, max 8
-	uint reflection_probe_count;
-	uint omni_light_count;
-	uint spot_light_count;
-	uint decal_count;
-	uvec4 reflection_probe_indices;
-	uvec4 omni_light_indices;
-	uvec4 spot_light_indices;
-	uvec4 decal_indices;
-} draw_data;
+#if 0
 
-layout(set = 3, binding = 0, std140) uniform InstanceData {
-	mat4 transform;
-	mat3 normal_transform;
-	uint flags;
-	uint pad0;
-	uint pad1;
-	uint pad2;
-} instance_data;
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
 
-layout(set = 3, binding = 1) uniform textureBuffer multimesh_transforms;
+layout(set = 3, binding = 2) uniform textureCubeArray reflection_probes[MAX_REFLECTION_PROBES];
 
-#ifdef USE_LIGHTMAP
+#else
 
-layout(set = 3, binding = 2) uniform texture2D lightmap;
+layout(set = 3, binding = 2) uniform textureCube reflection_probes[MAX_REFLECTION_PROBES];
 
 #endif
 
+
 #ifdef USE_VOXEL_CONE_TRACING
 
-layout(set = 3, binding = 3) uniform texture3D gi_probe[2];
+layout(set = 3, binding = 4) uniform texture3D gi_probe[2];
 
 #ifdef USE_ANISOTROPIC_VOXEL_CONE_TRACING
-layout(set = 3, binding = 4) uniform texture3D gi_probe_aniso_pos[2];
-layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_neg[2];
+layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_pos[2];
+layout(set = 3, binding = 6) uniform texture3D gi_probe_aniso_neg[2];
 #endif
 
 
 #endif
+#endif

+ 3 - 7
servers/visual/rasterizer_rd/shaders/tonemap.glsl

@@ -166,7 +166,9 @@ vec3 tonemap_reinhard(vec3 color, float white) {
 	return (white * color + color) / (color * white + white);
 }
 
-vec3 linear_to_srgb(vec3 color) { // convert linear rgb to srgb, assumes clamped input in range [0;1]
+vec3 linear_to_srgb(vec3 color) {
+	//if going to srgb, clamp from 0 to 1.
+	color = clamp(color,vec3(0.0),vec3(1.0));
 	const vec3 a = vec3(0.055f);
 	return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
 }
@@ -233,15 +235,9 @@ vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blendi
 		return color + glow;
 	} else if (params.glow_mode==GLOW_MODE_SCREEN) {
 		//need color clamping
-		color = clamp(color,0.0,1.0);
-		glow = clamp(glow,0.0,1.0);
-
 		return max((color + glow) - (color * glow), vec3(0.0));
 	} else if ( params.glow_mode==GLOW_MODE_SOFTLIGHT) {
 		//need color clamping
-		color = clamp(color,0.0,1.0);
-		glow = clamp(glow,0.0,1.0);
-
 		glow = glow * vec3(0.5f) + vec3(0.5f);
 
 		color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));

+ 2 - 2
servers/visual/visual_server_raster.cpp

@@ -103,9 +103,9 @@ void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) {
 
 	VSG::rasterizer->begin_frame(frame_step);
 
-	VSG::scene->update_dirty_instances(); //update scene stuff
+	VSG::scene_render->update(); //update scenes stuff before updating instances
 
-	VSG::scene_render->update();
+	VSG::scene->update_dirty_instances(); //update scene stuff
 
 	VSG::viewport->draw_viewports();
 	VSG::scene->render_probes();

+ 2 - 2
servers/visual/visual_server_raster.h

@@ -313,7 +313,6 @@ public:
 	BIND2(light_set_use_gi, RID, bool)
 
 	BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
-	BIND2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
 
 	BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
 	BIND2(light_directional_set_blend_splits, RID, bool)
@@ -489,6 +488,8 @@ public:
 //from now on, calls forwarded to this singleton
 #define BINDBASE VSG::scene_render
 
+	BIND1(directional_shadow_atlas_set_size, int)
+
 	/* SKY API */
 
 	BIND0R(RID, sky_create)
@@ -535,7 +536,6 @@ public:
 
 	BIND2(scenario_set_debug, RID, ScenarioDebugMode)
 	BIND2(scenario_set_environment, RID, RID)
-	BIND3(scenario_set_reflection_atlas_size, RID, int, int)
 	BIND2(scenario_set_fallback_environment, RID, RID)
 
 	/* INSTANCING API */

+ 8 - 51
servers/visual/visual_server_scene.cpp

@@ -268,7 +268,6 @@ RID VisualServerScene::scenario_create() {
 	VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);
 	VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);
 	VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);
-	scenario->reflection_atlas = VSG::scene_render->reflection_atlas_create();
 
 	return scenario_rid;
 }
@@ -294,14 +293,6 @@ void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_
 	scenario->fallback_environment = p_environment;
 }
 
-void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv) {
-
-	Scenario *scenario = scenario_owner.getornull(p_scenario);
-	ERR_FAIL_COND(!scenario);
-	VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_size);
-	VSG::scene_render->reflection_atlas_set_subdivision(scenario->reflection_atlas, p_subdiv);
-}
-
 /* INSTANCING API */
 
 void VisualServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
@@ -360,11 +351,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
 			instance->octree_id = 0;
 		}
 
-		if (instance->custom_data) {
-			VSG::scene_render->instance_free_custom_data(instance);
-			instance->custom_data = nullptr;
-		}
-
 		switch (instance->base_type) {
 			case VS::INSTANCE_LIGHT: {
 
@@ -494,8 +480,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
 
 		//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
 		VSG::storage->base_update_dependency(p_base, instance);
-
-		VSG::scene_render->instance_create_custom_data(instance);
 	}
 
 	_instance_queue_update(instance, true, true);
@@ -527,8 +511,6 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
 			} break;
 			case VS::INSTANCE_REFLECTION_PROBE: {
 
-				InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
-				VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
 			} break;
 			case VS::INSTANCE_GI_PROBE: {
 
@@ -710,10 +692,6 @@ void VisualServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap
 		lightmap_capture->users.insert(instance);
 		instance->lightmap = p_lightmap;
 	}
-
-	if (instance->custom_data) {
-		VSG::scene_render->instance_custom_data_update_lightmap(instance);
-	}
 }
 
 void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
@@ -943,10 +921,6 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
 
 	p_instance->transformed_aabb = new_aabb;
 
-	if (p_instance->custom_data) {
-		VSG::scene_render->instance_custom_data_update_transform(p_instance);
-	}
-
 	if (!p_instance->scenario) {
 
 		return;
@@ -1614,12 +1588,12 @@ bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
 					//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(-1, 0, 0),
 						Vector3(0, -1, 0),
 						Vector3(0, +1, 0),
-						Vector3(0, 0, -1),
-						Vector3(0, 0, +1)
+						Vector3(0, 0, +1),
+						Vector3(0, 0, -1)
 					};
 					static const Vector3 view_up[6] = {
 						Vector3(0, -1, 0),
@@ -1920,10 +1894,8 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
 							reflection_probe->reflection_dirty = false;
 						}
 
-						if (VSG::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++;
-						}
+						reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
+						reflection_probe_cull_count++;
 					}
 				}
 			}
@@ -1970,10 +1942,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
 				}
 
 				geom->lighting_dirty = false;
-
-				if (ins->custom_data) {
-					VSG::scene_render->instance_custom_data_update_lights(ins);
-				}
 			}
 
 			if (geom->reflection_dirty) {
@@ -1989,10 +1957,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
 				}
 
 				geom->reflection_dirty = false;
-
-				if (ins->custom_data) {
-					VSG::scene_render->instance_custom_data_update_reflection_probes(ins);
-				}
 			}
 
 			if (geom->gi_probes_dirty) {
@@ -2008,10 +1972,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
 				}
 
 				geom->gi_probes_dirty = false;
-
-				if (ins->custom_data) {
-					VSG::scene_render->instance_custom_data_update_gi_probes(ins);
-				}
 			}
 
 			ins->depth = near_plane.distance_to(ins->transform.origin);
@@ -2188,7 +2148,7 @@ void VisualServerScene::_render_scene(RID p_render_buffers, const Transform p_ca
 
 	/* PROCESS GEOMETRY AND DRAW SCENE */
 
-	VSG::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, environment, p_shadow_atlas, scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
+	VSG::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, environment, p_shadow_atlas, p_reflection_probe, p_reflection_probe_pass);
 }
 
 void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
@@ -2202,7 +2162,7 @@ void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario,
 		environment = scenario->environment;
 	else
 		environment = scenario->fallback_environment;
-	VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
+	VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, RID(), 0);
 #endif
 }
 
@@ -2216,9 +2176,7 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
 
 	if (p_step == 0) {
 
-		if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
-			return true; //sorry, all full :(
-		}
+		VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance);
 	}
 
 	if (p_step >= 0 && p_step < 6) {
@@ -3507,7 +3465,6 @@ bool VisualServerScene::free(RID p_rid) {
 			instance_set_scenario(scenario->instances.first()->self()->self, RID());
 		}
 		VSG::scene_render->free(scenario->reflection_probe_shadow_atlas);
-		VSG::scene_render->free(scenario->reflection_atlas);
 		scenario_owner.free(p_rid);
 		memdelete(scenario);
 

+ 0 - 2
servers/visual/visual_server_scene.h

@@ -115,7 +115,6 @@ public:
 		RID environment;
 		RID fallback_environment;
 		RID reflection_probe_shadow_atlas;
-		RID reflection_atlas;
 
 		SelfList<Instance>::List instances;
 
@@ -132,7 +131,6 @@ public:
 	virtual void scenario_set_debug(RID p_scenario, VS::ScenarioDebugMode p_debug_mode);
 	virtual void scenario_set_environment(RID p_scenario, RID p_environment);
 	virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
-	virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv);
 
 	/* INSTANCING API */
 

+ 2 - 2
servers/visual/visual_server_wrap_mt.h

@@ -240,7 +240,6 @@ public:
 	FUNC2(light_set_use_gi, RID, bool)
 
 	FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
-	FUNC2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
 
 	FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
 	FUNC2(light_directional_set_blend_splits, RID, bool)
@@ -404,6 +403,8 @@ public:
 
 	FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
 
+	FUNC1(directional_shadow_atlas_set_size, int)
+
 	/* SKY API */
 
 	FUNCRID(sky)
@@ -447,7 +448,6 @@ public:
 
 	FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
 	FUNC2(scenario_set_environment, RID, RID)
-	FUNC3(scenario_set_reflection_atlas_size, RID, int, int)
 	FUNC2(scenario_set_fallback_environment, RID, RID)
 
 	/* INSTANCING API */

+ 0 - 4
servers/visual_server.cpp

@@ -1694,7 +1694,6 @@ void VisualServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("light_set_use_gi", "light", "enabled"), &VisualServer::light_set_use_gi);
 
 	ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &VisualServer::light_omni_set_shadow_mode);
-	ClassDB::bind_method(D_METHOD("light_omni_set_shadow_detail", "light", "detail"), &VisualServer::light_omni_set_shadow_detail);
 
 	ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &VisualServer::light_directional_set_shadow_mode);
 	ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &VisualServer::light_directional_set_blend_splits);
@@ -1836,7 +1835,6 @@ void VisualServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("scenario_create"), &VisualServer::scenario_create);
 	ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &VisualServer::scenario_set_debug);
 	ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &VisualServer::scenario_set_environment);
-	ClassDB::bind_method(D_METHOD("scenario_set_reflection_atlas_size", "scenario", "size", "subdiv"), &VisualServer::scenario_set_reflection_atlas_size);
 	ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &VisualServer::scenario_set_fallback_environment);
 
 #ifndef _3D_DISABLED
@@ -2056,8 +2054,6 @@ void VisualServer::_bind_methods() {
 
 	BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID);
 	BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE);
-	BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DETAIL_VERTICAL);
-	BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL);
 
 	BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
 	BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS);

+ 5 - 10
servers/visual_server.h

@@ -432,14 +432,6 @@ public:
 
 	virtual void light_omni_set_shadow_mode(RID p_light, LightOmniShadowMode p_mode) = 0;
 
-	// omni light
-	enum LightOmniShadowDetail {
-		LIGHT_OMNI_SHADOW_DETAIL_VERTICAL,
-		LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL
-	};
-
-	virtual void light_omni_set_shadow_detail(RID p_light, LightOmniShadowDetail p_detail) = 0;
-
 	// directional light
 	enum LightDirectionalShadowMode {
 		LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL,
@@ -667,12 +659,17 @@ public:
 	enum ViewportDebugDraw {
 		VIEWPORT_DEBUG_DRAW_DISABLED,
 		VIEWPORT_DEBUG_DRAW_UNSHADED,
+		VIEWPORT_DEBUG_DRAW_LIGHTING,
 		VIEWPORT_DEBUG_DRAW_OVERDRAW,
 		VIEWPORT_DEBUG_DRAW_WIREFRAME,
+		VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS
+
 	};
 
 	virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0;
 
+	virtual void directional_shadow_atlas_set_size(int p_size) = 0;
+
 	/* SKY API */
 
 	enum SkyMode {
@@ -792,7 +789,6 @@ public:
 
 	virtual void scenario_set_debug(RID p_scenario, ScenarioDebugMode p_debug_mode) = 0;
 	virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
-	virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv) = 0;
 	virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
 
 	/* INSTANCING API */
@@ -1106,7 +1102,6 @@ VARIANT_ENUM_CAST(VisualServer::MultimeshTransformFormat);
 VARIANT_ENUM_CAST(VisualServer::MultimeshColorFormat);
 VARIANT_ENUM_CAST(VisualServer::MultimeshCustomDataFormat);
 VARIANT_ENUM_CAST(VisualServer::LightOmniShadowMode);
-VARIANT_ENUM_CAST(VisualServer::LightOmniShadowDetail);
 VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowMode);
 VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowDepthRangeMode);
 VARIANT_ENUM_CAST(VisualServer::ReflectionProbeUpdateMode);

Неке датотеке нису приказане због велике количине промена