diff --git a/core/math/basis.cpp b/core/math/basis.cpp index ddf5f13d559..14079f811de 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -244,6 +244,18 @@ void Basis::scale_local(const Vector3 &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 b; b.set_diagonal(p_scale); diff --git a/core/math/basis.h b/core/math/basis.h index 6c3a939d705..0261cf67c6e 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -108,6 +108,9 @@ public: void scale_local(const Vector3 &p_scale); Basis scaled_local(const Vector3 &p_scale) const; + void make_scale_uniform(); + float get_uniform_scale() const; + Vector3 get_scale() const; Vector3 get_scale_abs() const; Vector3 get_scale_local() const; diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 9e2d10c1f66..c4981b954b3 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -276,6 +276,36 @@ Vector2 CameraMatrix::get_viewport_half_extents() const { 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 { Vector planes = get_projection_planes(Transform()); diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index b5c75ca562f..60f7d159744 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -75,6 +75,7 @@ struct CameraMatrix { bool get_endpoints(const Transform &p_transform, Vector3 *p_8points) const; Vector2 get_viewport_half_extents() const; + void get_far_plane_size(real_t &r_width, real_t &r_height) const; void invert(); CameraMatrix inverse() const; @@ -93,6 +94,21 @@ struct CameraMatrix { 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(const Transform &p_transform); ~CameraMatrix(); diff --git a/servers/visual/rasterizer_rd/light_cluster_builder.cpp b/servers/visual/rasterizer_rd/light_cluster_builder.cpp new file mode 100644 index 00000000000..5236c5d1f26 --- /dev/null +++ b/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::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::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::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::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); + } +} diff --git a/servers/visual/rasterizer_rd/light_cluster_builder.h b/servers/visual/rasterizer_rd/light_cluster_builder.h new file mode 100644 index 00000000000..f3912623565 --- /dev/null +++ b/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 cluster_data; + RID cluster_texture; + + struct SortID { + uint32_t cell_index; + uint32_t item_index; + ItemType item_type; + }; + + SortID *sort_ids = nullptr; + PoolVector 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 diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_rd.cpp index b9fe0caf9d4..9a55235fa1b 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_rd.cpp @@ -175,5 +175,5 @@ RasterizerRD::RasterizerRD() { storage = memnew(RasterizerStorageRD); canvas = memnew(RasterizerCanvasRD(storage)); - scene = memnew(RasterizerSceneForwardRD(storage)); + scene = memnew(RasterizerSceneHighEndRD(storage)); } diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.h b/servers/visual/rasterizer_rd/rasterizer_rd.h index 60bc546aab4..0e95068a4fc 100644 --- a/servers/visual/rasterizer_rd/rasterizer_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_rd.h @@ -35,14 +35,14 @@ #include "core/thread_work_pool.h" #include "servers/visual/rasterizer.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" class RasterizerRD : public Rasterizer { protected: RasterizerCanvasRD *canvas; RasterizerStorageRD *storage; - RasterizerSceneForwardRD *scene; + RasterizerSceneHighEndRD *scene; RID copy_viewports_rd_shader; RID copy_viewports_rd_pipeline; diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp similarity index 94% rename from servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp rename to servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index 3959986f3ac..e7dafda072d 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -28,7 +28,7 @@ /* 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 "servers/visual/rendering_device.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 code = p_code; @@ -171,7 +171,7 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) { 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); @@ -346,14 +346,14 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) { 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()) { default_texture_params.erase(p_name); } else { default_texture_params[p_name] = p_texture; } } -void RasterizerSceneForwardRD::ShaderData::get_param_list(List *p_param_list) const { +void RasterizerSceneHighEndRD::ShaderData::get_param_list(List *p_param_list) const { Map order; @@ -374,7 +374,7 @@ void RasterizerSceneForwardRD::ShaderData::get_param_list(List *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)) { return false; } @@ -382,13 +382,13 @@ bool RasterizerSceneForwardRD::ShaderData::is_param_texture(const StringName &p_ return uniforms[p_param].texture_order >= 0; } -bool RasterizerSceneForwardRD::ShaderData::is_animated() const { +bool RasterizerSceneHighEndRD::ShaderData::is_animated() const { return false; } -bool RasterizerSceneForwardRD::ShaderData::casts_shadows() const { +bool RasterizerSceneHighEndRD::ShaderData::casts_shadows() const { 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)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector default_value = uniform.default_value; @@ -397,13 +397,13 @@ Variant RasterizerSceneForwardRD::ShaderData::get_default_parameter(const String return Variant(); } -RasterizerSceneForwardRD::ShaderData::ShaderData() { +RasterizerSceneHighEndRD::ShaderData::ShaderData() { valid = 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); //pipeline variants will clear themselves if shader is gone 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); 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 } -void RasterizerSceneForwardRD::MaterialData::set_next_pass(RID p_pass) { +void RasterizerSceneHighEndRD::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -void RasterizerSceneForwardRD::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map &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) { p_uniform_dirty = true; @@ -507,7 +507,7 @@ void RasterizerSceneForwardRD::MaterialData::update_parameters(const Mapuniform_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)) { 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); material_data->shader_data = p_shader; material_data->last_frame = false; @@ -525,11 +525,11 @@ RasterizerStorageRD::MaterialData *RasterizerSceneForwardRD::_create_material_fu return material_data; } -RasterizerSceneForwardRD::RenderBufferDataForward::~RenderBufferDataForward() { +RasterizerSceneHighEndRD::RenderBufferDataForward::~RenderBufferDataForward() { clear(); } -void RasterizerSceneForwardRD::RenderBufferDataForward::clear() { +void RasterizerSceneHighEndRD::RenderBufferDataForward::clear() { if (color_fb.is_valid()) { 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(); 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); } -bool RasterizerSceneForwardRD::free(RID p_rid) { +bool RasterizerSceneHighEndRD::free(RID p_rid) { if (RasterizerSceneRD::free(p_rid)) { return true; } 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++) { @@ -618,71 +618,6 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, id.gi_offset = 0xFFFFFFFF; 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()) { uint32_t written = 0; @@ -723,7 +658,7 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, /// 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::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; //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.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[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); } -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; @@ -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_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_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)); @@ -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); } -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++) { @@ -1365,6 +1303,8 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r Transform proj = (p_camera_inverse_transform * transform).inverse(); store_transform(proj, reflection_ubo.local_matrix); + cluster_builder.add_reflection_probe(transform, extents); + 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; @@ -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; 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[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); @@ -1546,7 +1487,8 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig 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)))); + 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); @@ -1593,6 +1535,8 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig 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++; } 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; 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; } - _update_render_base_uniform_set(); - bool using_shadows = true; if (p_reflection_probe.is_valid()) { @@ -1704,10 +1646,16 @@ void RasterizerSceneForwardRD::_render_scene(RID p_render_buffer, const Transfor 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_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_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(); _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 #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"); @@ -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_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(), 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(); @@ -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"); _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_slope_scale = 0; - scene_state.ubo.z_far = 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(); @@ -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()) { @@ -2098,13 +2044,28 @@ void RasterizerSceneForwardRD::_update_render_base_uniform_set() { 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); 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)) { 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); } -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; RasterizerSceneRD::set_time(p_time, p_step); } -RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storage) : +RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage) : RasterizerSceneRD(p_storage) { singleton = this; storage = p_storage; @@ -2495,9 +2456,11 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag sampler.compare_op = RD::COMPARE_OP_LESS; 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 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); diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h similarity index 95% rename from servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h rename to servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h index dd86c8ae272..ddc38fb4ca2 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -28,15 +28,16 @@ /* 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_storage_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 */ @@ -56,7 +57,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { }; struct { - SceneForwardShaderRD scene_shader; + SceneHighEndShaderRD scene_shader; ShaderCompilerRD compiler; } shader; @@ -151,7 +152,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { RasterizerStorageRD::ShaderData *_create_shader_func(); static RasterizerStorageRD::ShaderData *_create_shader_funcs() { - return static_cast(singleton)->_create_shader_func(); + return static_cast(singleton)->_create_shader_func(); } struct MaterialData : public RasterizerStorageRD::MaterialData { @@ -173,7 +174,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { - return static_cast(singleton)->_create_material_func(static_cast(p_shader)); + return static_cast(singleton)->_create_material_func(static_cast(p_shader)); } /* Push Constant */ @@ -282,11 +283,6 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { 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 { @@ -321,7 +317,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { uint32_t directional_light_count; float dual_paraboloid_side; float z_far; - uint32_t pad[1]; + float z_near; }; UBO ubo; @@ -497,7 +493,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { RenderList render_list; - static RasterizerSceneForwardRD *singleton; + static RasterizerSceneHighEndRD *singleton; uint64_t render_pass; double time; RID default_shader; @@ -511,6 +507,8 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { RID default_vec4_xform_buffer; RID default_vec4_xform_uniform_set; + LightClusterBuilder cluster_builder; + enum PassMode { PASS_MODE_COLOR, PASS_MODE_COLOR_SPECULAR, @@ -523,7 +521,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD { 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_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); @@ -547,7 +545,7 @@ public: 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 diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub index 194d7d6c0ea..6151d9bd9ff 100644 --- a/servers/visual/rasterizer_rd/shaders/SCsub +++ b/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('blur.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('tonemap.glsl'); env.RD_GLSL('copy.glsl'); diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl similarity index 97% rename from servers/visual/rasterizer_rd/shaders/scene_forward.glsl rename to servers/visual/rasterizer_rd/shaders/scene_high_end.glsl index e4addc6fb59..7b36f240103 100644 --- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl +++ b/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl @@ -5,7 +5,7 @@ VERSION_DEFINES -#include "scene_forward_inc.glsl" +#include "scene_high_end_inc.glsl" /* INPUT ATTRIBS */ @@ -276,7 +276,7 @@ VERTEX_SHADER_CODE VERSION_DEFINES -#include "scene_forward_inc.glsl" +#include "scene_high_end_inc.glsl" /* Varyings */ @@ -1236,9 +1236,7 @@ void main() { float normaldepth = 1.0; -#if defined(SCREEN_UV_USED) vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; -#endif float sss_strength = 0.0; @@ -1394,23 +1392,20 @@ FRAGMENT_SHADER_CODE } } #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 vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); - uint reflection_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++) { - 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); } @@ -1527,22 +1522,18 @@ FRAGMENT_SHADER_CODE } { //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++) { - 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, #ifdef LIGHT_TRANSMISSION_USED transmission, @@ -1565,22 +1556,17 @@ FRAGMENT_SHADER_CODE } { //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++) { - 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, #ifdef LIGHT_TRANSMISSION_USED transmission, diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl similarity index 95% rename from servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl rename to servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl index 5701781808c..6ad5559b082 100644 --- a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl +++ b/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; float dual_paraboloid_side; float z_far; - uint pad0; + float z_near; #if 0 vec4 ambient_light_color; @@ -118,11 +118,6 @@ struct InstanceData { 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 = 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]; +#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 */ layout(set = 1, binding = 0) uniform texture2D depth_buffer; diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 60ea292d8f6..47e2d11af94 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -2302,7 +2302,7 @@ VisualServer::VisualServer() { GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false); 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.mobile", true);