Browse Source

Modified rendering to use cluster instead of foward

Juan Linietsky 5 years ago
parent
commit
ee1e89f8c0

+ 12 - 0
core/math/basis.cpp

@@ -244,6 +244,18 @@ void Basis::scale_local(const Vector3 &p_scale) {
 	*this = scaled_local(p_scale);
 	*this = scaled_local(p_scale);
 }
 }
 
 
+float Basis::get_uniform_scale() const {
+	return (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0;
+}
+
+void Basis::make_scale_uniform() {
+	float l = (elements[0].length() + elements[1].length() + elements[2].length()) / 3.0;
+	for (int i = 0; i < 3; i++) {
+		elements[i].normalize();
+		elements[i] *= l;
+	}
+}
+
 Basis Basis::scaled_local(const Vector3 &p_scale) const {
 Basis Basis::scaled_local(const Vector3 &p_scale) const {
 	Basis b;
 	Basis b;
 	b.set_diagonal(p_scale);
 	b.set_diagonal(p_scale);

+ 3 - 0
core/math/basis.h

@@ -108,6 +108,9 @@ public:
 	void scale_local(const Vector3 &p_scale);
 	void scale_local(const Vector3 &p_scale);
 	Basis scaled_local(const Vector3 &p_scale) const;
 	Basis scaled_local(const Vector3 &p_scale) const;
 
 
+	void make_scale_uniform();
+	float get_uniform_scale() const;
+
 	Vector3 get_scale() const;
 	Vector3 get_scale() const;
 	Vector3 get_scale_abs() const;
 	Vector3 get_scale_abs() const;
 	Vector3 get_scale_local() const;
 	Vector3 get_scale_local() const;

+ 30 - 0
core/math/camera_matrix.cpp

@@ -276,6 +276,36 @@ Vector2 CameraMatrix::get_viewport_half_extents() const {
 	return Vector2(res.x, res.y);
 	return Vector2(res.x, res.y);
 }
 }
 
 
+void CameraMatrix::get_far_plane_size(real_t &r_width, real_t &r_height) const {
+
+	const real_t *matrix = (const real_t *)this->matrix;
+	///////--- Far Plane ---///////
+	Plane far_plane = Plane(matrix[3] - matrix[2],
+			matrix[7] - matrix[6],
+			matrix[11] - matrix[10],
+			-matrix[15] + matrix[14]);
+	far_plane.normalize();
+
+	///////--- Right Plane ---///////
+	Plane right_plane = Plane(matrix[3] - matrix[0],
+			matrix[7] - matrix[4],
+			matrix[11] - matrix[8],
+			-matrix[15] + matrix[12]);
+	right_plane.normalize();
+
+	Plane top_plane = Plane(matrix[3] - matrix[1],
+			matrix[7] - matrix[5],
+			matrix[11] - matrix[9],
+			-matrix[15] + matrix[13]);
+	top_plane.normalize();
+
+	Vector3 res;
+	far_plane.intersect_3(right_plane, top_plane, &res);
+
+	r_width = res.x;
+	r_height = res.y;
+}
+
 bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
 bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
 
 
 	Vector<Plane> planes = get_projection_planes(Transform());
 	Vector<Plane> planes = get_projection_planes(Transform());

+ 16 - 0
core/math/camera_matrix.h

@@ -75,6 +75,7 @@ struct CameraMatrix {
 
 
 	bool get_endpoints(const Transform &p_transform, Vector3 *p_8points) const;
 	bool get_endpoints(const Transform &p_transform, Vector3 *p_8points) const;
 	Vector2 get_viewport_half_extents() const;
 	Vector2 get_viewport_half_extents() const;
+	void get_far_plane_size(real_t &r_width, real_t &r_height) const;
 
 
 	void invert();
 	void invert();
 	CameraMatrix inverse() const;
 	CameraMatrix inverse() const;
@@ -93,6 +94,21 @@ struct CameraMatrix {
 
 
 	void flip_y();
 	void flip_y();
 
 
+	bool operator==(const CameraMatrix &p_cam) const {
+		for (uint32_t i = 0; i < 4; i++) {
+			for (uint32_t j = 0; j < 4; j++) {
+				if (matrix[i][j] != p_cam.matrix[i][j]) {
+					return false;
+				}
+			}
+		}
+		return true;
+	}
+
+	bool operator!=(const CameraMatrix &p_cam) const {
+		return !(*this == p_cam);
+	}
+
 	CameraMatrix();
 	CameraMatrix();
 	CameraMatrix(const Transform &p_transform);
 	CameraMatrix(const Transform &p_transform);
 	~CameraMatrix();
 	~CameraMatrix();

+ 230 - 0
servers/visual/rasterizer_rd/light_cluster_builder.cpp

@@ -0,0 +1,230 @@
+#include "light_cluster_builder.h"
+
+void LightClusterBuilder::begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection) {
+	view_xform = p_view_transform;
+	projection = p_cam_projection;
+	z_near = -projection.get_z_near();
+	z_far = -projection.get_z_far();
+
+	//reset counts
+	light_count = 0;
+	refprobe_count = 0;
+	item_count = 0;
+	sort_id_count = 0;
+}
+
+void LightClusterBuilder::bake_cluster() {
+
+	float slice_depth = (z_near - z_far) / depth;
+
+	PoolVector<uint8_t>::Write cluster_dataw = cluster_data.write();
+	Cell *cluster_data_ptr = (Cell *)cluster_dataw.ptr();
+	//clear the cluster
+	zeromem(cluster_data_ptr, (width * height * depth * sizeof(Cell)));
+
+	/* Step 1, create cell positions and count them */
+
+	for (uint32_t i = 0; i < item_count; i++) {
+
+		const Item &item = items[i];
+
+		int from_slice = Math::floor((z_near - (item.aabb.position.z + item.aabb.size.z)) / slice_depth);
+		int to_slice = Math::floor((z_near - item.aabb.position.z) / slice_depth);
+
+		if (from_slice >= (int)depth || to_slice < 0) {
+			continue; //sorry no go
+		}
+
+		from_slice = MAX(0, from_slice);
+		to_slice = MIN((int)depth - 1, to_slice);
+
+		for (int j = from_slice; j <= to_slice; j++) {
+
+			Vector3 min = item.aabb.position;
+			Vector3 max = item.aabb.position + item.aabb.size;
+
+			float limit_near = MIN((z_near - slice_depth * j), max.z);
+			float limit_far = MAX((z_near - slice_depth * (j + 1)), min.z);
+
+			max.z = limit_near;
+			min.z = limit_near;
+
+			Vector3 proj_min = projection.xform(min);
+			Vector3 proj_max = projection.xform(max);
+
+			int near_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width));
+			int near_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height));
+			int near_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width));
+			int near_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height));
+
+			max.z = limit_far;
+			min.z = limit_far;
+
+			proj_min = projection.xform(min);
+			proj_max = projection.xform(max);
+
+			int far_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width));
+			int far_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height));
+			int far_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width));
+			int far_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height));
+
+			//print_line(itos(j) + " near - " + Vector2i(near_from_x, near_from_y) + " -> " + Vector2i(near_to_x, near_to_y));
+			//print_line(itos(j) + " far - " + Vector2i(far_from_x, far_from_y) + " -> " + Vector2i(far_to_x, far_to_y));
+
+			int from_x = MIN(near_from_x, far_from_x);
+			int from_y = MIN(near_from_y, far_from_y);
+			int to_x = MAX(near_to_x, far_to_x);
+			int to_y = MAX(near_to_y, far_to_y);
+
+			if (from_x >= (int)width || to_x < 0 || from_y >= (int)height || to_y < 0) {
+				continue;
+			}
+
+			int sx = MAX(0, from_x);
+			int sy = MAX(0, from_y);
+			int dx = MIN(width - 1, to_x);
+			int dy = MIN(height - 1, to_y);
+
+			//print_line(itos(j) + " - " + Vector2i(sx, sy) + " -> " + Vector2i(dx, dy));
+
+			for (int x = sx; x <= dx; x++) {
+				for (int y = sy; y <= dy; y++) {
+					uint32_t offset = j * (width * height) + y * width + x;
+
+					if (unlikely(sort_id_count == sort_id_max)) {
+						sort_id_max = nearest_power_of_2_templated(sort_id_max + 1);
+						sort_ids = (SortID *)memrealloc(sort_ids, sizeof(SortID) * sort_id_max);
+						if (ids.size()) {
+
+							ids.resize(sort_id_max);
+							RD::get_singleton()->free(items_buffer);
+							items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * sort_id_max);
+						}
+					}
+
+					sort_ids[sort_id_count].cell_index = offset;
+					sort_ids[sort_id_count].item_index = item.index;
+					sort_ids[sort_id_count].item_type = item.type;
+
+					sort_id_count++;
+
+					//for now, only count
+					cluster_data_ptr[offset].item_pointers[item.type]++;
+					//print_line("at offset " + itos(offset) + " value: " + itos(cluster_data_ptr[offset].item_pointers[item.type]));
+				}
+			}
+		}
+	}
+
+	/* Step 2, Assign pointers (and reset counters) */
+
+	uint32_t offset = 0;
+	for (uint32_t i = 0; i < (width * height * depth); i++) {
+		for (int j = 0; j < ITEM_TYPE_MAX; j++) {
+			uint32_t count = cluster_data_ptr[i].item_pointers[j]; //save count
+			cluster_data_ptr[i].item_pointers[j] = offset; //replace count by pointer
+			offset += count; //increase offset by count;
+		}
+	}
+
+	//print_line("offset: " + itos(offset));
+	/* Step 3, Place item lists */
+
+	PoolVector<uint32_t>::Write idsw = ids.write();
+	uint32_t *ids_ptr = idsw.ptr();
+
+	for (uint32_t i = 0; i < sort_id_count; i++) {
+		const SortID &id = sort_ids[i];
+		Cell &cell = cluster_data_ptr[id.cell_index];
+		uint32_t pointer = cell.item_pointers[id.item_type] & POINTER_MASK;
+		uint32_t counter = cell.item_pointers[id.item_type] >> COUNTER_SHIFT;
+		ids_ptr[pointer + counter] = id.item_index;
+
+		cell.item_pointers[id.item_type] = pointer | ((counter + 1) << COUNTER_SHIFT);
+	}
+
+	cluster_dataw = PoolVector<uint8_t>::Write();
+
+	RD::get_singleton()->texture_update(cluster_texture, 0, cluster_data, true);
+	RD::get_singleton()->buffer_update(items_buffer, 0, offset * sizeof(uint32_t), ids_ptr, true);
+
+	idsw = PoolVector<uint32_t>::Write();
+}
+
+void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth) {
+
+	if (width == p_width && height == p_height && depth == p_depth) {
+		return;
+	}
+	if (cluster_texture.is_valid()) {
+		RD::get_singleton()->free(cluster_texture);
+	}
+
+	width = p_width;
+	height = p_height;
+	depth = p_depth;
+
+	cluster_data.resize(width * height * depth * sizeof(Cell));
+
+	{
+		RD::TextureFormat tf;
+		tf.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+		tf.type = RD::TEXTURE_TYPE_3D;
+		tf.width = width;
+		tf.height = height;
+		tf.depth = depth;
+		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+
+		cluster_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+	}
+}
+
+RID LightClusterBuilder::get_cluster_texture() const {
+	return cluster_texture;
+}
+RID LightClusterBuilder::get_cluster_indices_buffer() const {
+	return items_buffer;
+}
+
+LightClusterBuilder::LightClusterBuilder() {
+	//initialize accumulators to something
+	lights = (LightData *)memalloc(sizeof(LightData) * 1024);
+	light_max = 1024;
+
+	refprobes = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024);
+	refprobe_max = 1024;
+
+	decals = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024);
+	decal_max = 1024;
+
+	items = (Item *)memalloc(sizeof(Item) * 1024);
+	item_max = 1024;
+
+	sort_ids = (SortID *)memalloc(sizeof(SortID) * 1024);
+	ids.resize(2014);
+	items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 1024);
+	item_max = 1024;
+}
+LightClusterBuilder::~LightClusterBuilder() {
+
+	if (cluster_data.size()) {
+		RD::get_singleton()->free(cluster_texture);
+	}
+
+	if (lights) {
+		memfree(lights);
+	}
+	if (refprobes) {
+		memfree(refprobes);
+	}
+	if (decals) {
+		memfree(decals);
+	}
+	if (items) {
+		memfree(items);
+	}
+	if (sort_ids) {
+		memfree(sort_ids);
+		RD::get_singleton()->free(items_buffer);
+	}
+}

+ 261 - 0
servers/visual/rasterizer_rd/light_cluster_builder.h

@@ -0,0 +1,261 @@
+#ifndef LIGHT_CLUSTER_BUILDER_H
+#define LIGHT_CLUSTER_BUILDER_H
+
+#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
+
+class LightClusterBuilder {
+public:
+	enum LightType {
+		LIGHT_TYPE_OMNI,
+		LIGHT_TYPE_SPOT
+	};
+
+	enum ItemType {
+		ITEM_TYPE_OMNI_LIGHT,
+		ITEM_TYPE_SPOT_LIGHT,
+		ITEM_TYPE_REFLECTION_PROBE,
+		ITEM_TYPE_DECAL,
+		ITEM_TYPE_MAX //should always be 4
+	};
+
+	enum {
+		COUNTER_SHIFT = 20, //one million total ids
+		POINTER_MASK = (1 << COUNTER_SHIFT) - 1,
+		COUNTER_MASK = 0xfff // 4096 items per cell
+	};
+
+private:
+	struct LightData {
+		float position[3];
+		uint32_t type;
+		float radius;
+		float spot_aperture;
+		uint32_t pad[2];
+	};
+
+	uint32_t light_count = 0;
+	uint32_t light_max = 0;
+	LightData *lights = nullptr;
+
+	struct OrientedBoxData {
+		float position[3];
+		uint32_t pad;
+		float x_axis[3];
+		uint32_t pad2;
+		float y_axis[3];
+		uint32_t pad3;
+		float z_axis[3];
+		uint32_t pad4;
+	};
+
+	uint32_t refprobe_count = 0;
+	uint32_t refprobe_max = 0;
+	OrientedBoxData *refprobes = nullptr;
+
+	uint32_t decal_count = 0;
+	uint32_t decal_max = 0;
+	OrientedBoxData *decals = nullptr;
+
+	struct Item {
+		AABB aabb;
+		ItemType type;
+		uint32_t index;
+	};
+
+	Item *items = nullptr;
+	uint32_t item_count = 0;
+	uint32_t item_max = 0;
+
+	uint32_t width = 0;
+	uint32_t height = 0;
+	uint32_t depth = 0;
+
+	struct Cell {
+		uint32_t item_pointers[ITEM_TYPE_MAX];
+	};
+
+	PoolVector<uint8_t> cluster_data;
+	RID cluster_texture;
+
+	struct SortID {
+		uint32_t cell_index;
+		uint32_t item_index;
+		ItemType item_type;
+	};
+
+	SortID *sort_ids = nullptr;
+	PoolVector<uint32_t> ids;
+	uint32_t sort_id_count = 0;
+	uint32_t sort_id_max = 0;
+	RID items_buffer;
+
+	Transform view_xform;
+	CameraMatrix projection;
+	float z_far = 0;
+	float z_near = 0;
+
+	_FORCE_INLINE_ void _add_item(const AABB &p_aabb, ItemType p_type, uint32_t p_index) {
+		if (unlikely(item_count == item_max)) {
+			item_max = nearest_power_of_2_templated(item_max + 1);
+			items = (Item *)memrealloc(items, sizeof(Item) * item_max);
+		}
+
+		Item &item = items[item_count];
+		item.aabb = p_aabb;
+		item.index = p_index;
+		item.type = p_type;
+		item_count++;
+	}
+
+public:
+	void begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection);
+
+	_FORCE_INLINE_ void add_light(LightType p_type, const Transform &p_transform, float p_radius, float p_spot_aperture) {
+		if (unlikely(light_count == light_max)) {
+			light_max = nearest_power_of_2_templated(light_max + 1);
+			lights = (LightData *)memrealloc(lights, sizeof(LightData) * light_max);
+		}
+
+		LightData &ld = lights[light_count];
+		ld.type = p_type;
+		ld.position[0] = p_transform.origin.x;
+		ld.position[1] = p_transform.origin.y;
+		ld.position[2] = p_transform.origin.z;
+		ld.radius = p_radius;
+		ld.spot_aperture = p_spot_aperture;
+
+		Transform xform = view_xform * p_transform;
+
+		ld.radius *= xform.basis.get_uniform_scale();
+
+		AABB aabb;
+
+		switch (p_type) {
+			case LIGHT_TYPE_OMNI: {
+				aabb.position = xform.origin;
+				aabb.size = Vector3(ld.radius, ld.radius, ld.radius);
+				aabb.position -= aabb.size;
+				aabb.size *= 2.0;
+
+				_add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count);
+			} break;
+			case LIGHT_TYPE_SPOT: {
+				Vector3 v(0, 0, -1);
+				v.rotated(Vector3(0, 1, 0), Math::deg2rad(ld.spot_aperture)); //rotate in x-z
+				v.normalize();
+				v *= ld.radius;
+				v.y = v.x;
+
+				aabb.position = xform.origin;
+				aabb.expand_to(xform.xform(v));
+				aabb.expand_to(xform.xform(Vector3(-v.x, v.y, v.z)));
+				aabb.expand_to(xform.xform(Vector3(-v.x, -v.y, v.z)));
+				aabb.expand_to(xform.xform(Vector3(v.x, -v.y, v.z)));
+				_add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count);
+			} break;
+		}
+
+		light_count++;
+	}
+
+	_FORCE_INLINE_ void add_reflection_probe(const Transform &p_transform, const Vector3 &p_half_extents) {
+
+		if (unlikely(refprobe_count == refprobe_max)) {
+			refprobe_max = nearest_power_of_2_templated(refprobe_max + 1);
+			refprobes = (OrientedBoxData *)memrealloc(refprobes, sizeof(OrientedBoxData) * refprobe_max);
+		}
+
+		OrientedBoxData &rp = refprobes[refprobe_count];
+		Vector3 origin = p_transform.origin;
+		rp.position[0] = origin.x;
+		rp.position[1] = origin.y;
+		rp.position[2] = origin.z;
+
+		Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x;
+		rp.x_axis[0] = x_axis.x;
+		rp.x_axis[1] = x_axis.y;
+		rp.x_axis[2] = x_axis.z;
+
+		Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y;
+		rp.y_axis[0] = y_axis.x;
+		rp.y_axis[1] = y_axis.y;
+		rp.y_axis[2] = y_axis.z;
+
+		Vector3 z_axis = p_transform.basis.get_axis(2) * p_half_extents.z;
+		rp.z_axis[0] = z_axis.x;
+		rp.z_axis[1] = z_axis.y;
+		rp.z_axis[2] = z_axis.z;
+
+		AABB aabb;
+
+		aabb.position = origin + x_axis + y_axis + z_axis;
+		aabb.expand_to(origin + x_axis + y_axis - z_axis);
+		aabb.expand_to(origin + x_axis - y_axis + z_axis);
+		aabb.expand_to(origin + x_axis - y_axis - z_axis);
+		aabb.expand_to(origin - x_axis + y_axis + z_axis);
+		aabb.expand_to(origin - x_axis + y_axis - z_axis);
+		aabb.expand_to(origin - x_axis - y_axis + z_axis);
+		aabb.expand_to(origin - x_axis - y_axis - z_axis);
+
+		_add_item(aabb, ITEM_TYPE_REFLECTION_PROBE, refprobe_count);
+
+		refprobe_count++;
+	}
+
+	_FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector2 &p_half_extents, float p_depth) {
+
+		if (unlikely(decal_count == decal_max)) {
+			decal_max = nearest_power_of_2_templated(decal_max + 1);
+			decals = (OrientedBoxData *)memrealloc(decals, sizeof(OrientedBoxData) * decal_max);
+		}
+
+		OrientedBoxData &dc = decals[decal_count];
+
+		Vector3 z_axis = -p_transform.basis.get_axis(2) * p_depth * 0.5;
+		dc.z_axis[0] = z_axis.x;
+		dc.z_axis[1] = z_axis.y;
+		dc.z_axis[2] = z_axis.z;
+
+		Vector3 origin = p_transform.origin - z_axis;
+		dc.position[0] = origin.x;
+		dc.position[1] = origin.y;
+		dc.position[2] = origin.z;
+
+		Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x;
+		dc.x_axis[0] = x_axis.x;
+		dc.x_axis[1] = x_axis.y;
+		dc.x_axis[2] = x_axis.z;
+
+		Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y;
+		dc.y_axis[0] = y_axis.x;
+		dc.y_axis[1] = y_axis.y;
+		dc.y_axis[2] = y_axis.z;
+
+		AABB aabb;
+
+		aabb.position = origin + x_axis + y_axis + z_axis;
+		aabb.expand_to(origin + x_axis + y_axis - z_axis);
+		aabb.expand_to(origin + x_axis - y_axis + z_axis);
+		aabb.expand_to(origin + x_axis - y_axis - z_axis);
+		aabb.expand_to(origin - x_axis + y_axis + z_axis);
+		aabb.expand_to(origin - x_axis + y_axis - z_axis);
+		aabb.expand_to(origin - x_axis - y_axis + z_axis);
+		aabb.expand_to(origin - x_axis - y_axis - z_axis);
+
+		_add_item(aabb, ITEM_TYPE_DECAL, decal_count);
+
+		decal_count++;
+	}
+
+	void bake_cluster();
+
+	void setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth);
+
+	RID get_cluster_texture() const;
+	RID get_cluster_indices_buffer() const;
+
+	LightClusterBuilder();
+	~LightClusterBuilder();
+};
+
+#endif // LIGHT_CLUSTER_BUILDER_H

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

@@ -175,5 +175,5 @@ RasterizerRD::RasterizerRD() {
 
 
 	storage = memnew(RasterizerStorageRD);
 	storage = memnew(RasterizerStorageRD);
 	canvas = memnew(RasterizerCanvasRD(storage));
 	canvas = memnew(RasterizerCanvasRD(storage));
-	scene = memnew(RasterizerSceneForwardRD(storage));
+	scene = memnew(RasterizerSceneHighEndRD(storage));
 }
 }

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

@@ -35,14 +35,14 @@
 #include "core/thread_work_pool.h"
 #include "core/thread_work_pool.h"
 #include "servers/visual/rasterizer.h"
 #include "servers/visual/rasterizer.h"
 #include "servers/visual/rasterizer_rd/rasterizer_canvas_rd.h"
 #include "servers/visual/rasterizer_rd/rasterizer_canvas_rd.h"
-#include "servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h"
+#include "servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h"
 #include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
 #include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
 
 
 class RasterizerRD : public Rasterizer {
 class RasterizerRD : public Rasterizer {
 protected:
 protected:
 	RasterizerCanvasRD *canvas;
 	RasterizerCanvasRD *canvas;
 	RasterizerStorageRD *storage;
 	RasterizerStorageRD *storage;
-	RasterizerSceneForwardRD *scene;
+	RasterizerSceneHighEndRD *scene;
 
 
 	RID copy_viewports_rd_shader;
 	RID copy_viewports_rd_shader;
 	RID copy_viewports_rd_pipeline;
 	RID copy_viewports_rd_pipeline;

+ 80 - 117
servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp → servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp

@@ -28,7 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#include "rasterizer_scene_forward_rd.h"
+#include "rasterizer_scene_high_end_rd.h"
 #include "core/project_settings.h"
 #include "core/project_settings.h"
 #include "servers/visual/rendering_device.h"
 #include "servers/visual/rendering_device.h"
 #include "servers/visual/visual_server_raster.h"
 #include "servers/visual/visual_server_raster.h"
@@ -88,7 +88,7 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_arra
 		}
 		}
 	}
 	}
 }
 }
-void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
+void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) {
 	//compile
 	//compile
 
 
 	code = p_code;
 	code = p_code;
@@ -171,7 +171,7 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
 
 
 	actions.uniforms = &uniforms;
 	actions.uniforms = &uniforms;
 
 
-	RasterizerSceneForwardRD *scene_singleton = (RasterizerSceneForwardRD *)RasterizerSceneForwardRD::singleton;
+	RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton;
 
 
 	Error err = scene_singleton->shader.compiler.compile(VS::SHADER_SPATIAL, code, &actions, path, gen_code);
 	Error err = scene_singleton->shader.compiler.compile(VS::SHADER_SPATIAL, code, &actions, path, gen_code);
 
 
@@ -346,14 +346,14 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
 	valid = true;
 	valid = true;
 }
 }
 
 
-void RasterizerSceneForwardRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
+void RasterizerSceneHighEndRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
 	if (!p_texture.is_valid()) {
 	if (!p_texture.is_valid()) {
 		default_texture_params.erase(p_name);
 		default_texture_params.erase(p_name);
 	} else {
 	} else {
 		default_texture_params[p_name] = p_texture;
 		default_texture_params[p_name] = p_texture;
 	}
 	}
 }
 }
-void RasterizerSceneForwardRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RasterizerSceneHighEndRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
 
 
 	Map<int, StringName> order;
 	Map<int, StringName> order;
 
 
@@ -374,7 +374,7 @@ void RasterizerSceneForwardRD::ShaderData::get_param_list(List<PropertyInfo> *p_
 	}
 	}
 }
 }
 
 
-bool RasterizerSceneForwardRD::ShaderData::is_param_texture(const StringName &p_param) const {
+bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_param) const {
 	if (!uniforms.has(p_param)) {
 	if (!uniforms.has(p_param)) {
 		return false;
 		return false;
 	}
 	}
@@ -382,13 +382,13 @@ bool RasterizerSceneForwardRD::ShaderData::is_param_texture(const StringName &p_
 	return uniforms[p_param].texture_order >= 0;
 	return uniforms[p_param].texture_order >= 0;
 }
 }
 
 
-bool RasterizerSceneForwardRD::ShaderData::is_animated() const {
+bool RasterizerSceneHighEndRD::ShaderData::is_animated() const {
 	return false;
 	return false;
 }
 }
-bool RasterizerSceneForwardRD::ShaderData::casts_shadows() const {
+bool RasterizerSceneHighEndRD::ShaderData::casts_shadows() const {
 	return false;
 	return false;
 }
 }
-Variant RasterizerSceneForwardRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant RasterizerSceneHighEndRD::ShaderData::get_default_parameter(const StringName &p_parameter) const {
 	if (uniforms.has(p_parameter)) {
 	if (uniforms.has(p_parameter)) {
 		ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
 		ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
 		Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
 		Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
@@ -397,13 +397,13 @@ Variant RasterizerSceneForwardRD::ShaderData::get_default_parameter(const String
 	return Variant();
 	return Variant();
 }
 }
 
 
-RasterizerSceneForwardRD::ShaderData::ShaderData() {
+RasterizerSceneHighEndRD::ShaderData::ShaderData() {
 	valid = false;
 	valid = false;
 	uses_screen_texture = false;
 	uses_screen_texture = false;
 }
 }
 
 
-RasterizerSceneForwardRD::ShaderData::~ShaderData() {
-	RasterizerSceneForwardRD *scene_singleton = (RasterizerSceneForwardRD *)RasterizerSceneForwardRD::singleton;
+RasterizerSceneHighEndRD::ShaderData::~ShaderData() {
+	RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton;
 	ERR_FAIL_COND(!scene_singleton);
 	ERR_FAIL_COND(!scene_singleton);
 	//pipeline variants will clear themselves if shader is gone
 	//pipeline variants will clear themselves if shader is gone
 	if (version.is_valid()) {
 	if (version.is_valid()) {
@@ -411,22 +411,22 @@ RasterizerSceneForwardRD::ShaderData::~ShaderData() {
 	}
 	}
 }
 }
 
 
-RasterizerStorageRD::ShaderData *RasterizerSceneForwardRD::_create_shader_func() {
+RasterizerStorageRD::ShaderData *RasterizerSceneHighEndRD::_create_shader_func() {
 	ShaderData *shader_data = memnew(ShaderData);
 	ShaderData *shader_data = memnew(ShaderData);
 	return shader_data;
 	return shader_data;
 }
 }
 
 
-void RasterizerSceneForwardRD::MaterialData::set_render_priority(int p_priority) {
+void RasterizerSceneHighEndRD::MaterialData::set_render_priority(int p_priority) {
 	priority = p_priority - VS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits
 	priority = p_priority - VS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits
 }
 }
 
 
-void RasterizerSceneForwardRD::MaterialData::set_next_pass(RID p_pass) {
+void RasterizerSceneHighEndRD::MaterialData::set_next_pass(RID p_pass) {
 	next_pass = p_pass;
 	next_pass = p_pass;
 }
 }
 
 
-void RasterizerSceneForwardRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
 
 
-	RasterizerSceneForwardRD *scene_singleton = (RasterizerSceneForwardRD *)RasterizerSceneForwardRD::singleton;
+	RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton;
 
 
 	if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
 	if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
 		p_uniform_dirty = true;
 		p_uniform_dirty = true;
@@ -507,7 +507,7 @@ void RasterizerSceneForwardRD::MaterialData::update_parameters(const Map<StringN
 
 
 	uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), 3);
 	uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), 3);
 }
 }
-RasterizerSceneForwardRD::MaterialData::~MaterialData() {
+RasterizerSceneHighEndRD::MaterialData::~MaterialData() {
 	if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
 	if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
 		RD::get_singleton()->free(uniform_set);
 		RD::get_singleton()->free(uniform_set);
 	}
 	}
@@ -517,7 +517,7 @@ RasterizerSceneForwardRD::MaterialData::~MaterialData() {
 	}
 	}
 }
 }
 
 
-RasterizerStorageRD::MaterialData *RasterizerSceneForwardRD::_create_material_func(ShaderData *p_shader) {
+RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_material_func(ShaderData *p_shader) {
 	MaterialData *material_data = memnew(MaterialData);
 	MaterialData *material_data = memnew(MaterialData);
 	material_data->shader_data = p_shader;
 	material_data->shader_data = p_shader;
 	material_data->last_frame = false;
 	material_data->last_frame = false;
@@ -525,11 +525,11 @@ RasterizerStorageRD::MaterialData *RasterizerSceneForwardRD::_create_material_fu
 	return material_data;
 	return material_data;
 }
 }
 
 
-RasterizerSceneForwardRD::RenderBufferDataForward::~RenderBufferDataForward() {
+RasterizerSceneHighEndRD::RenderBufferDataForward::~RenderBufferDataForward() {
 	clear();
 	clear();
 }
 }
 
 
-void RasterizerSceneForwardRD::RenderBufferDataForward::clear() {
+void RasterizerSceneHighEndRD::RenderBufferDataForward::clear() {
 
 
 	if (color_fb.is_valid()) {
 	if (color_fb.is_valid()) {
 		RD::get_singleton()->free(color_fb);
 		RD::get_singleton()->free(color_fb);
@@ -537,7 +537,7 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::clear() {
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) {
+void RasterizerSceneHighEndRD::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) {
 	clear();
 	clear();
 
 
 	width = p_width;
 	width = p_width;
@@ -567,18 +567,18 @@ void RasterizerSceneForwardRD::RenderBufferDataForward::configure(RID p_color_bu
 	}
 	}
 }
 }
 
 
-RasterizerSceneRD::RenderBufferData *RasterizerSceneForwardRD::_create_render_buffer_data() {
+RasterizerSceneRD::RenderBufferData *RasterizerSceneHighEndRD::_create_render_buffer_data() {
 	return memnew(RenderBufferDataForward);
 	return memnew(RenderBufferDataForward);
 }
 }
 
 
-bool RasterizerSceneForwardRD::free(RID p_rid) {
+bool RasterizerSceneHighEndRD::free(RID p_rid) {
 	if (RasterizerSceneRD::free(p_rid)) {
 	if (RasterizerSceneRD::free(p_rid)) {
 		return true;
 		return true;
 	}
 	}
 	return false;
 	return false;
 }
 }
 
 
-void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth) {
+void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth) {
 
 
 	for (int i = 0; i < p_element_count; i++) {
 	for (int i = 0; i < p_element_count; i++) {
 
 
@@ -618,71 +618,6 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements,
 			id.gi_offset = 0xFFFFFFFF;
 			id.gi_offset = 0xFFFFFFFF;
 			continue;
 			continue;
 		}
 		}
-		//forward
-
-		uint32_t reflection_count = 0;
-		uint32_t omni_count = 0;
-		uint32_t spot_count = 0;
-		uint32_t decal_count = 0;
-
-		if (!e->instance->reflection_probe_instances.empty()) {
-
-			uint32_t rpi_count = e->instance->reflection_probe_instances.size();
-			const RID *rpi_ptrs = e->instance->reflection_probe_instances.ptr();
-
-			for (uint32_t j = 0; j < rpi_count; j++) {
-				if (render_pass != reflection_probe_instance_get_render_pass(rpi_ptrs[j])) {
-					continue; //not rendered this frame
-				}
-
-				RID base = reflection_probe_instance_get_probe(rpi_ptrs[j]);
-
-				uint32_t mask = storage->reflection_probe_get_cull_mask(base);
-				if (!(mask & id.mask)) {
-					continue; //masked
-				}
-
-				if (reflection_count < 8) {
-					id.reflection_probe_indices[reflection_count] = reflection_probe_instance_get_render_index(rpi_ptrs[j]);
-					reflection_count++;
-				}
-			}
-		}
-
-		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
-				}
-
-				RID base = light_instance_get_base_light(light_ptrs[j]);
-
-				uint32_t mask = storage->light_get_cull_mask(base);
-				if (!(mask & id.mask)) {
-					continue; //masked
-				}
-
-				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.spot_light_indices[spot_count] = light_instance_get_index(light_ptrs[j]);
-						spot_count++;
-					}
-				}
-			}
-		}
-
-		id.flags |= reflection_count;
-		id.flags |= omni_count << 3;
-		id.flags |= spot_count << 6;
-		id.flags |= decal_count << 9;
 
 
 		if (!e->instance->gi_probe_instances.empty()) {
 		if (!e->instance->gi_probe_instances.empty()) {
 			uint32_t written = 0;
 			uint32_t written = 0;
@@ -723,7 +658,7 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements,
 
 
 /// RENDERING ///
 /// RENDERING ///
 
 
-void RasterizerSceneForwardRD::_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) {
+void RasterizerSceneHighEndRD::_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) {
 
 
 	RD::DrawListID draw_list = p_draw_list;
 	RD::DrawListID draw_list = p_draw_list;
 	RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
 	RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -923,7 +858,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color) {
+void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar) {
 
 
 	//CameraMatrix projection = p_cam_projection;
 	//CameraMatrix projection = p_cam_projection;
 	//projection.flip_y(); // Vulkan and modern APIs use Y-Down
 	//projection.flip_y(); // Vulkan and modern APIs use Y-Down
@@ -937,6 +872,9 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const Camer
 	store_transform(p_cam_transform, scene_state.ubo.camera_matrix);
 	store_transform(p_cam_transform, scene_state.ubo.camera_matrix);
 	store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
 	store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
 
 
+	scene_state.ubo.z_far = p_zfar;
+	scene_state.ubo.z_near = p_znear;
+
 	scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
 	scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
 	scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
 	scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
 
 
@@ -1030,7 +968,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_environment, const Camer
 	RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
 	RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
 }
 }
 
 
-void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
+void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
 
 
 	RID m_src;
 	RID m_src;
 
 
@@ -1073,7 +1011,7 @@ void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index) {
+void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index) {
 
 
 	bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
 	bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
 	bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
 	bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
@@ -1153,7 +1091,7 @@ void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_insta
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi) {
+void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi) {
 
 
 	scene_state.current_shader_index = 0;
 	scene_state.current_shader_index = 0;
 	scene_state.current_material_index = 0;
 	scene_state.current_material_index = 0;
@@ -1264,7 +1202,7 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_draw_sky(RD::DrawListID p_draw_list, RD::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha) {
+void RasterizerSceneHighEndRD::_draw_sky(RD::DrawListID p_draw_list, RD::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha) {
 
 
 	ERR_FAIL_COND(!is_environment(p_environment));
 	ERR_FAIL_COND(!is_environment(p_environment));
 
 
@@ -1296,7 +1234,7 @@ 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);
 	storage->get_effects()->render_panorama(p_draw_list, p_fb_format, panorama, camera, sky_transform, 1.0, multiplier);
 }
 }
 
 
-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) {
+void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
 
 
 	for (int i = 0; i < p_reflection_probe_cull_count; i++) {
 	for (int i = 0; i < p_reflection_probe_cull_count; i++) {
 
 
@@ -1365,6 +1303,8 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r
 		Transform proj = (p_camera_inverse_transform * transform).inverse();
 		Transform proj = (p_camera_inverse_transform * transform).inverse();
 		store_transform(proj, reflection_ubo.local_matrix);
 		store_transform(proj, reflection_ubo.local_matrix);
 
 
+		cluster_builder.add_reflection_probe(transform, extents);
+
 		reflection_probe_instance_set_render_pass(rpi, render_pass);
 		reflection_probe_instance_set_render_pass(rpi, render_pass);
 	}
 	}
 
 
@@ -1373,7 +1313,7 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform) {
+void RasterizerSceneHighEndRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform) {
 
 
 	int index = 0;
 	int index = 0;
 
 
@@ -1428,7 +1368,7 @@ void RasterizerSceneForwardRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_resul
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows) {
+void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows) {
 
 
 	uint32_t light_count = 0;
 	uint32_t light_count = 0;
 	scene_state.ubo.directional_light_count = 0;
 	scene_state.ubo.directional_light_count = 0;
@@ -1531,7 +1471,8 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
 				light_data.color_specular[2] = CLAMP(uint32_t(linear_col.b * 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.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));
+				float radius = MAX(0.001, storage->light_get_param(base, VS::LIGHT_PARAM_RANGE));
+				light_data.inv_radius = 1.0 / radius;
 
 
 				Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin);
 				Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin);
 
 
@@ -1546,7 +1487,8 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
 				light_data.direction[2] = direction.z;
 				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[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))));
+				float spot_angle = storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ANGLE);
+				light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(spot_angle)));
 
 
 				light_data.mask = storage->light_get_cull_mask(base);
 				light_data.mask = storage->light_get_cull_mask(base);
 
 
@@ -1593,6 +1535,8 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
 
 
 				light_instance_set_index(li, light_count);
 				light_instance_set_index(li, light_count);
 
 
+				cluster_builder.add_light(type == VS::LIGHT_SPOT ? LightClusterBuilder::LIGHT_TYPE_SPOT : LightClusterBuilder::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
+
 				light_count++;
 				light_count++;
 			} break;
 			} break;
 		}
 		}
@@ -1611,7 +1555,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_render_scene(RID p_render_buffer, 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_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) {
+void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, 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_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) {
 
 
 	RenderBufferDataForward *render_buffer = NULL;
 	RenderBufferDataForward *render_buffer = NULL;
 	if (p_render_buffer.is_valid()) {
 	if (p_render_buffer.is_valid()) {
@@ -1652,8 +1596,6 @@ void RasterizerSceneForwardRD::_render_scene(RID p_render_buffer, const Transfor
 		p_gi_probe_cull_count = 0;
 		p_gi_probe_cull_count = 0;
 	}
 	}
 
 
-	_update_render_base_uniform_set();
-
 	bool using_shadows = true;
 	bool using_shadows = true;
 
 
 	if (p_reflection_probe.is_valid()) {
 	if (p_reflection_probe.is_valid()) {
@@ -1704,10 +1646,16 @@ void RasterizerSceneForwardRD::_render_scene(RID p_render_buffer, const Transfor
 		ERR_FAIL(); //bug?
 		ERR_FAIL(); //bug?
 	}
 	}
 
 
+	cluster_builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
+
 	_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
 	_setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
 	_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
 	_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
 	_setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform);
 	_setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform);
-	_setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color);
+	_setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far());
+
+	cluster_builder.bake_cluster(); //bake to cluster
+
+	_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
 
 
 	render_list.clear();
 	render_list.clear();
 	_fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr);
 	_fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr);
@@ -1899,7 +1847,7 @@ void RasterizerSceneForwardRD::_render_scene(RID p_render_buffer, const Transfor
 	//disable all stuff
 	//disable all stuff
 #endif
 #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 RasterizerSceneHighEndRD::_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) {
 
 
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 
 
@@ -1909,10 +1857,9 @@ void RasterizerSceneForwardRD::_render_shadow(RID p_framebuffer, InstanceBase **
 
 
 	scene_state.ubo.shadow_z_offset = p_bias;
 	scene_state.ubo.shadow_z_offset = p_bias;
 	scene_state.ubo.shadow_z_slope_scale = p_normal_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;
 	scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
 
 
-	_setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color());
+	_setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar);
 
 
 	render_list.clear();
 	render_list.clear();
 
 
@@ -1936,7 +1883,7 @@ void RasterizerSceneForwardRD::_render_shadow(RID p_framebuffer, InstanceBase **
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
+void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 	RENDER_TIMESTAMP("Setup Rendering Shadow");
 
 
 	_update_render_base_uniform_set();
 	_update_render_base_uniform_set();
@@ -1945,10 +1892,9 @@ void RasterizerSceneForwardRD::_render_material(const Transform &p_cam_transform
 
 
 	scene_state.ubo.shadow_z_offset = 0;
 	scene_state.ubo.shadow_z_offset = 0;
 	scene_state.ubo.shadow_z_slope_scale = 0;
 	scene_state.ubo.shadow_z_slope_scale = 0;
-	scene_state.ubo.z_far = 0;
 	scene_state.ubo.dual_paraboloid_side = 0;
 	scene_state.ubo.dual_paraboloid_side = 0;
 
 
-	_setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color());
+	_setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
 
 
 	render_list.clear();
 	render_list.clear();
 
 
@@ -1977,7 +1923,7 @@ void RasterizerSceneForwardRD::_render_material(const Transform &p_cam_transform
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_update_render_base_uniform_set() {
+void RasterizerSceneHighEndRD::_update_render_base_uniform_set() {
 
 
 	if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || gi_probe_slots_are_dirty()) {
 	if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || gi_probe_slots_are_dirty()) {
 
 
@@ -2098,13 +2044,28 @@ void RasterizerSceneForwardRD::_update_render_base_uniform_set() {
 			uniforms.push_back(u);
 			uniforms.push_back(u);
 		}
 		}
 
 
+		{
+			RD::Uniform u;
+			u.binding = 10;
+			u.type = RD::UNIFORM_TYPE_TEXTURE;
+			u.ids.push_back(cluster_builder.get_cluster_texture());
+			uniforms.push_back(u);
+		}
+		{
+			RD::Uniform u;
+			u.binding = 11;
+			u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+			u.ids.push_back(cluster_builder.get_cluster_indices_buffer());
+			uniforms.push_back(u);
+		}
+
 		render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0);
 		render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0);
 
 
 		gi_probe_slots_make_not_dirty();
 		gi_probe_slots_make_not_dirty();
 	}
 	}
 }
 }
 
 
-void RasterizerSceneForwardRD::_setup_render_pass_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) {
+void RasterizerSceneHighEndRD::_setup_render_pass_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_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
 	if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
 		RD::get_singleton()->free(render_pass_uniform_set);
 		RD::get_singleton()->free(render_pass_uniform_set);
@@ -2200,14 +2161,14 @@ void RasterizerSceneForwardRD::_setup_render_pass_uniform_set(RID p_depth_buffer
 	render_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 1);
 	render_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 1);
 }
 }
 
 
-RasterizerSceneForwardRD *RasterizerSceneForwardRD::singleton = NULL;
+RasterizerSceneHighEndRD *RasterizerSceneHighEndRD::singleton = NULL;
 
 
-void RasterizerSceneForwardRD::set_time(double p_time, double p_step) {
+void RasterizerSceneHighEndRD::set_time(double p_time, double p_step) {
 	time = p_time;
 	time = p_time;
 	RasterizerSceneRD::set_time(p_time, p_step);
 	RasterizerSceneRD::set_time(p_time, p_step);
 }
 }
 
 
-RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storage) :
+RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage) :
 		RasterizerSceneRD(p_storage) {
 		RasterizerSceneRD(p_storage) {
 	singleton = this;
 	singleton = this;
 	storage = p_storage;
 	storage = p_storage;
@@ -2495,9 +2456,11 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
 		sampler.compare_op = RD::COMPARE_OP_LESS;
 		sampler.compare_op = RD::COMPARE_OP_LESS;
 		shadow_sampler = RD::get_singleton()->sampler_create(sampler);
 		shadow_sampler = RD::get_singleton()->sampler_create(sampler);
 	}
 	}
+
+	cluster_builder.setup(16, 8, 24);
 }
 }
 
 
-RasterizerSceneForwardRD::~RasterizerSceneForwardRD() {
+RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() {
 	//clear base uniform set if still valid
 	//clear base uniform set if still valid
 	if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
 	if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
 		RD::get_singleton()->free(render_pass_uniform_set);
 		RD::get_singleton()->free(render_pass_uniform_set);

+ 16 - 18
servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h → servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h

@@ -28,15 +28,16 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#ifndef RASTERIZER_SCENE_FORWARD_RD_H
-#define RASTERIZER_SCENE_FORWARD_RD_H
+#ifndef RASTERIZER_SCENE_HIGHEND_RD_H
+#define RASTERIZER_SCENE_HIGHEND_RD_H
 
 
+#include "servers/visual/rasterizer_rd/light_cluster_builder.h"
 #include "servers/visual/rasterizer_rd/rasterizer_scene_rd.h"
 #include "servers/visual/rasterizer_rd/rasterizer_scene_rd.h"
 #include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
 #include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
 #include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
 #include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
-#include "servers/visual/rasterizer_rd/shaders/scene_forward.glsl.gen.h"
+#include "servers/visual/rasterizer_rd/shaders/scene_high_end.glsl.gen.h"
 
 
-class RasterizerSceneForwardRD : public RasterizerSceneRD {
+class RasterizerSceneHighEndRD : public RasterizerSceneRD {
 
 
 	/* Shader */
 	/* Shader */
 
 
@@ -56,7 +57,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 	};
 	};
 
 
 	struct {
 	struct {
-		SceneForwardShaderRD scene_shader;
+		SceneHighEndShaderRD scene_shader;
 		ShaderCompilerRD compiler;
 		ShaderCompilerRD compiler;
 	} shader;
 	} shader;
 
 
@@ -151,7 +152,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 
 
 	RasterizerStorageRD::ShaderData *_create_shader_func();
 	RasterizerStorageRD::ShaderData *_create_shader_func();
 	static RasterizerStorageRD::ShaderData *_create_shader_funcs() {
 	static RasterizerStorageRD::ShaderData *_create_shader_funcs() {
-		return static_cast<RasterizerSceneForwardRD *>(singleton)->_create_shader_func();
+		return static_cast<RasterizerSceneHighEndRD *>(singleton)->_create_shader_func();
 	}
 	}
 
 
 	struct MaterialData : public RasterizerStorageRD::MaterialData {
 	struct MaterialData : public RasterizerStorageRD::MaterialData {
@@ -173,7 +174,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 
 
 	RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
 	RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
 	static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
 	static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
-		return static_cast<RasterizerSceneForwardRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
+		return static_cast<RasterizerSceneHighEndRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
 	}
 	}
 
 
 	/* Push Constant */
 	/* Push Constant */
@@ -282,11 +283,6 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 		uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer
 		uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer
 		uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
 		uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
 		uint32_t mask;
 		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 SceneState {
@@ -321,7 +317,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 			uint32_t directional_light_count;
 			uint32_t directional_light_count;
 			float dual_paraboloid_side;
 			float dual_paraboloid_side;
 			float z_far;
 			float z_far;
-			uint32_t pad[1];
+			float z_near;
 		};
 		};
 
 
 		UBO ubo;
 		UBO ubo;
@@ -497,7 +493,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 
 
 	RenderList render_list;
 	RenderList render_list;
 
 
-	static RasterizerSceneForwardRD *singleton;
+	static RasterizerSceneHighEndRD *singleton;
 	uint64_t render_pass;
 	uint64_t render_pass;
 	double time;
 	double time;
 	RID default_shader;
 	RID default_shader;
@@ -511,6 +507,8 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 	RID default_vec4_xform_buffer;
 	RID default_vec4_xform_buffer;
 	RID default_vec4_xform_uniform_set;
 	RID default_vec4_xform_uniform_set;
 
 
+	LightClusterBuilder cluster_builder;
+
 	enum PassMode {
 	enum PassMode {
 		PASS_MODE_COLOR,
 		PASS_MODE_COLOR,
 		PASS_MODE_COLOR_SPECULAR,
 		PASS_MODE_COLOR_SPECULAR,
@@ -523,7 +521,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
 		PASS_MODE_DEPTH_MATERIAL,
 		PASS_MODE_DEPTH_MATERIAL,
 	};
 	};
 
 
-	void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color);
+	void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar);
 	void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
 	void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
 	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 _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
 	void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
 	void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
@@ -547,7 +545,7 @@ public:
 
 
 	virtual bool free(RID p_rid);
 	virtual bool free(RID p_rid);
 
 
-	RasterizerSceneForwardRD(RasterizerStorageRD *p_storage);
-	~RasterizerSceneForwardRD();
+	RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage);
+	~RasterizerSceneHighEndRD();
 };
 };
-#endif // RASTERIZER_SCENE_FORWARD_RD_H
+#endif // RASTERIZER_SCENE_HIGHEND_RD_H

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

@@ -7,7 +7,7 @@ if 'RD_GLSL' in env['BUILDERS']:
     env.RD_GLSL('canvas_occlusion.glsl');
     env.RD_GLSL('canvas_occlusion.glsl');
     env.RD_GLSL('blur.glsl');
     env.RD_GLSL('blur.glsl');
     env.RD_GLSL('cubemap_roughness.glsl');
     env.RD_GLSL('cubemap_roughness.glsl');
-    env.RD_GLSL('scene_forward.glsl');
+    env.RD_GLSL('scene_high_end.glsl');
     env.RD_GLSL('sky.glsl');
     env.RD_GLSL('sky.glsl');
     env.RD_GLSL('tonemap.glsl');
     env.RD_GLSL('tonemap.glsl');
     env.RD_GLSL('copy.glsl');
     env.RD_GLSL('copy.glsl');

+ 21 - 35
servers/visual/rasterizer_rd/shaders/scene_forward.glsl → servers/visual/rasterizer_rd/shaders/scene_high_end.glsl

@@ -5,7 +5,7 @@
 
 
 VERSION_DEFINES
 VERSION_DEFINES
 
 
-#include "scene_forward_inc.glsl"
+#include "scene_high_end_inc.glsl"
 
 
 /* INPUT ATTRIBS */
 /* INPUT ATTRIBS */
 
 
@@ -276,7 +276,7 @@ VERTEX_SHADER_CODE
 
 
 VERSION_DEFINES
 VERSION_DEFINES
 
 
-#include "scene_forward_inc.glsl"
+#include "scene_high_end_inc.glsl"
 
 
 /* Varyings */
 /* Varyings */
 
 
@@ -1236,9 +1236,7 @@ void main() {
 
 
 	float normaldepth = 1.0;
 	float normaldepth = 1.0;
 
 
-#if defined(SCREEN_UV_USED)
 	vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size;
 	vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size;
-#endif
 
 
 	float sss_strength = 0.0;
 	float sss_strength = 0.0;
 
 
@@ -1394,23 +1392,20 @@ FRAGMENT_SHADER_CODE
 		}
 		}
 	}
 	}
 #endif
 #endif
+
+	uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]),vec3(screen_uv,(abs(vertex.z)-scene_data.z_near)/(scene_data.z_far-scene_data.z_near)));
+
 	{ // process reflections
 	{ // process reflections
 
 
 		vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
 		vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
 		vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
 		vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
 
 
-		uint reflection_probe_count = instances.data[instance_index].flags & INSTANCE_FLAGS_FORWARD_MASK;
+		uint reflection_probe_count = cluster_cell.z >> CLUSTER_COUNTER_SHIFT;
+		uint reflection_probe_pointer = cluster_cell.z & CLUSTER_POINTER_MASK;
 
 
 		for (uint i = 0; i < reflection_probe_count; i++) {
 		for (uint i = 0; i < reflection_probe_count; i++) {
 
 
-			uint ref_index = instances.data[instance_index].reflection_probe_indices[i >> 1];
-
-			if (bool(i & 1)) {
-				ref_index >>= 16;
-			} else {
-				ref_index &= 0xFFFF;
-			}
-
+			uint ref_index = cluster_data.indices[reflection_probe_pointer + i];
 			reflection_process(ref_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
 			reflection_process(ref_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
 		}
 		}
 
 
@@ -1527,22 +1522,18 @@ FRAGMENT_SHADER_CODE
 	}
 	}
 
 
 	{ //omni lights
 	{ //omni lights
-		uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
+
+		uint omni_light_count = cluster_cell.x >> CLUSTER_COUNTER_SHIFT;
+		uint omni_light_pointer = cluster_cell.x & CLUSTER_POINTER_MASK;
+
 		for (uint i = 0; i < omni_light_count; i++) {
 		for (uint i = 0; i < omni_light_count; i++) {
 
 
-			uint light_index = instances.data[instance_index].omni_light_indices[i >> 1];
+			uint light_index = cluster_data.indices[omni_light_pointer + i];
 
 
-			if (bool(i & 1)) {
-				light_index >>= 16;
-			} else {
-				light_index &= 0xFFFF;
+			if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
+				continue; //not masked
 			}
 			}
 
 
-			//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,
 			light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
 #ifdef LIGHT_TRANSMISSION_USED
 #ifdef LIGHT_TRANSMISSION_USED
 					transmission,
 					transmission,
@@ -1565,22 +1556,17 @@ FRAGMENT_SHADER_CODE
 	}
 	}
 
 
 	{ //spot lights
 	{ //spot lights
-		uint spot_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
+		uint spot_light_count = cluster_cell.y >> CLUSTER_COUNTER_SHIFT;
+		uint spot_light_pointer = cluster_cell.y & CLUSTER_POINTER_MASK;
+
 		for (uint i = 0; i < spot_light_count; i++) {
 		for (uint i = 0; i < spot_light_count; i++) {
 
 
-			uint light_index = instances.data[instance_index].spot_light_indices[i >> 1];
+			uint light_index = cluster_data.indices[spot_light_pointer + i];
 
 
-			if (bool(i & 1)) {
-				light_index >>= 16;
-			} else {
-				light_index &= 0xFFFF;
+			if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
+				continue; //not masked
 			}
 			}
 
 
-			//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,
 			light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity,
 #ifdef LIGHT_TRANSMISSION_USED
 #ifdef LIGHT_TRANSMISSION_USED
 					transmission,
 					transmission,

+ 11 - 6
servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl → servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl

@@ -58,7 +58,7 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
 	uint directional_light_count;
 	uint directional_light_count;
 	float dual_paraboloid_side;
 	float dual_paraboloid_side;
 	float z_far;
 	float z_far;
-	uint pad0;
+	float z_near;
 
 
 #if 0
 #if 0
 	vec4 ambient_light_color;
 	vec4 ambient_light_color;
@@ -118,11 +118,6 @@ struct InstanceData {
 	uint instance_ofs; //instance_offset in instancing/skeleton buffer
 	uint instance_ofs; //instance_offset in instancing/skeleton buffer
 	uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
 	uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
 	uint layer_mask;
 	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 = 4, std430) buffer Instances {
 layout(set = 0, binding = 4, std430) buffer Instances {
@@ -206,6 +201,16 @@ layout(set = 0, binding = 8, std140) uniform GIProbes {
 
 
 layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
 layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
 
 
+#define CLUSTER_COUNTER_SHIFT 20
+#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1)
+#define CLUSTER_COUNTER_MASK 0xfff
+
+layout(set = 0, binding = 10) uniform utexture3D cluster_texture;
+
+layout(set = 0, binding = 11, std430) buffer ClusterData {
+	uint indices[];
+} cluster_data;
+
 /* Set 1, Scene data that changes per render pass */
 /* Set 1, Scene data that changes per render pass */
 
 
 layout(set = 1, binding = 0) uniform texture2D depth_buffer;
 layout(set = 1, binding = 0) uniform texture2D depth_buffer;

+ 1 - 1
servers/visual_server.cpp

@@ -2302,7 +2302,7 @@ VisualServer::VisualServer() {
 
 
 	GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false);
 	GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false);
 	GLOBAL_DEF("rendering/quality/gi_probes/quality", 1);
 	GLOBAL_DEF("rendering/quality/gi_probes/quality", 1);
-	ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Ultra-Low (1 cone, fastest),Medium (4 cones), High (6 cones, slowest)"));
+	ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Ultra-Low (1 cone - fastest),Medium (4 cones), High (6 cones - slowest)"));
 
 
 	GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false);
 	GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false);
 	GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true);
 	GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true);