|
@@ -52,7 +52,8 @@ public:
|
|
RendererSceneRender *scene_render;
|
|
RendererSceneRender *scene_render;
|
|
|
|
|
|
enum {
|
|
enum {
|
|
- SDFGI_MAX_CASCADES = 8
|
|
|
|
|
|
+ SDFGI_MAX_CASCADES = 8,
|
|
|
|
+ SDFGI_MAX_REGIONS_PER_CASCADE = 3
|
|
};
|
|
};
|
|
|
|
|
|
uint64_t render_pass;
|
|
uint64_t render_pass;
|
|
@@ -108,6 +109,153 @@ public:
|
|
|
|
|
|
struct Instance;
|
|
struct Instance;
|
|
|
|
|
|
|
|
+ struct PlaneSign {
|
|
|
|
+ _ALWAYS_INLINE_ PlaneSign() {}
|
|
|
|
+ _ALWAYS_INLINE_ PlaneSign(const Plane &p_plane) {
|
|
|
|
+ if (p_plane.normal.x > 0) {
|
|
|
|
+ signs[0] = 0;
|
|
|
|
+ } else {
|
|
|
|
+ signs[0] = 3;
|
|
|
|
+ }
|
|
|
|
+ if (p_plane.normal.y > 0) {
|
|
|
|
+ signs[1] = 1;
|
|
|
|
+ } else {
|
|
|
|
+ signs[1] = 4;
|
|
|
|
+ }
|
|
|
|
+ if (p_plane.normal.z > 0) {
|
|
|
|
+ signs[2] = 2;
|
|
|
|
+ } else {
|
|
|
|
+ signs[2] = 5;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ uint32_t signs[3];
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ struct Frustum {
|
|
|
|
+ Vector<Plane> planes;
|
|
|
|
+ Vector<PlaneSign> plane_signs;
|
|
|
|
+ const Plane *planes_ptr;
|
|
|
|
+ const PlaneSign *plane_signs_ptr;
|
|
|
|
+ uint32_t plane_count;
|
|
|
|
+
|
|
|
|
+ _ALWAYS_INLINE_ Frustum() {}
|
|
|
|
+ _ALWAYS_INLINE_ Frustum(const Frustum &p_frustum) {
|
|
|
|
+ planes = p_frustum.planes;
|
|
|
|
+ plane_signs = p_frustum.plane_signs;
|
|
|
|
+
|
|
|
|
+ planes_ptr = planes.ptr();
|
|
|
|
+ plane_signs_ptr = plane_signs.ptr();
|
|
|
|
+ plane_count = p_frustum.plane_count;
|
|
|
|
+ }
|
|
|
|
+ _ALWAYS_INLINE_ void operator=(const Frustum &p_frustum) {
|
|
|
|
+ planes = p_frustum.planes;
|
|
|
|
+ plane_signs = p_frustum.plane_signs;
|
|
|
|
+
|
|
|
|
+ planes_ptr = planes.ptr();
|
|
|
|
+ plane_signs_ptr = plane_signs.ptr();
|
|
|
|
+ plane_count = p_frustum.plane_count;
|
|
|
|
+ }
|
|
|
|
+ _ALWAYS_INLINE_ Frustum(const Vector<Plane> &p_planes) {
|
|
|
|
+ planes = p_planes;
|
|
|
|
+ planes_ptr = planes.ptrw();
|
|
|
|
+ plane_count = planes.size();
|
|
|
|
+ for (int i = 0; i < planes.size(); i++) {
|
|
|
|
+ PlaneSign ps(p_planes[i]);
|
|
|
|
+ plane_signs.push_back(ps);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ plane_signs_ptr = plane_signs.ptr();
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ struct InstanceBounds {
|
|
|
|
+ // Efficiently store instance bounds.
|
|
|
|
+ // Because bounds checking is performed first,
|
|
|
|
+ // keep it separated from data.
|
|
|
|
+
|
|
|
|
+ real_t bounds[6];
|
|
|
|
+ _ALWAYS_INLINE_ InstanceBounds() {}
|
|
|
|
+
|
|
|
|
+ _ALWAYS_INLINE_ InstanceBounds(const AABB &p_aabb) {
|
|
|
|
+ bounds[0] = p_aabb.position.x;
|
|
|
|
+ bounds[1] = p_aabb.position.y;
|
|
|
|
+ bounds[2] = p_aabb.position.z;
|
|
|
|
+ bounds[3] = p_aabb.position.x + p_aabb.size.x;
|
|
|
|
+ bounds[4] = p_aabb.position.y + p_aabb.size.y;
|
|
|
|
+ bounds[5] = p_aabb.position.z + p_aabb.size.z;
|
|
|
|
+ }
|
|
|
|
+ _ALWAYS_INLINE_ bool in_frustum(const Frustum &p_frustum) const {
|
|
|
|
+ // This is not a full SAT check and the possibility of false positives exist,
|
|
|
|
+ // but the tradeoff vs performance is still very good.
|
|
|
|
+
|
|
|
|
+ for (uint32_t i = 0; i < p_frustum.plane_count; i++) {
|
|
|
|
+ Vector3 min(
|
|
|
|
+ bounds[p_frustum.plane_signs_ptr[i].signs[0]],
|
|
|
|
+ bounds[p_frustum.plane_signs_ptr[i].signs[1]],
|
|
|
|
+ bounds[p_frustum.plane_signs_ptr[i].signs[2]]);
|
|
|
|
+
|
|
|
|
+ if (p_frustum.planes_ptr[i].distance_to(min) >= 0.0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ _ALWAYS_INLINE_ bool in_aabb(const AABB &p_aabb) const {
|
|
|
|
+ Vector3 end = p_aabb.position + p_aabb.size;
|
|
|
|
+
|
|
|
|
+ if (bounds[0] >= end.x) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (bounds[3] <= p_aabb.position.x) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (bounds[1] >= end.y) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (bounds[4] <= p_aabb.position.y) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (bounds[2] >= end.z) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ if (bounds[5] <= p_aabb.position.z) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ struct InstanceData {
|
|
|
|
+ // Store instance pointer as well as common instance processing information,
|
|
|
|
+ // to make processing more cache friendly.
|
|
|
|
+ enum Flags {
|
|
|
|
+ FLAG_BASE_TYPE_MASK = 0xFF,
|
|
|
|
+ FLAG_CAST_SHADOWS = (1 << 8),
|
|
|
|
+ FLAG_CAST_SHADOWS_ONLY = (1 << 9),
|
|
|
|
+ FLAG_REDRAW_IF_VISIBLE = (1 << 10),
|
|
|
|
+ FLAG_GEOM_LIGHTING_DIRTY = (1 << 11),
|
|
|
|
+ FLAG_GEOM_REFLECTION_DIRTY = (1 << 12),
|
|
|
|
+ FLAG_GEOM_DECAL_DIRTY = (1 << 13),
|
|
|
|
+ FLAG_GEOM_GI_PROBE_DIRTY = (1 << 14),
|
|
|
|
+ FLAG_LIGHTMAP_CAPTURE = (1 << 15),
|
|
|
|
+ FLAG_USES_BAKED_LIGHT = (1 << 16),
|
|
|
|
+ FLAG_USES_MESH_INSTANCE = (1 << 17),
|
|
|
|
+ FLAG_REFLECTION_PROBE_DIRTY = (1 << 18),
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ uint32_t flags = 0;
|
|
|
|
+ uint32_t layer_mask = 0; //for fast layer-mask discard
|
|
|
|
+ RID base_rid;
|
|
|
|
+ RID instance_data_rid;
|
|
|
|
+ Instance *instance = nullptr;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ PagedArrayPool<InstanceBounds> instance_aabb_page_pool;
|
|
|
|
+ PagedArrayPool<InstanceData> instance_data_page_pool;
|
|
|
|
+
|
|
struct Scenario {
|
|
struct Scenario {
|
|
enum IndexerType {
|
|
enum IndexerType {
|
|
INDEXER_GEOMETRY, //for geometry
|
|
INDEXER_GEOMETRY, //for geometry
|
|
@@ -131,6 +279,9 @@ public:
|
|
|
|
|
|
LocalVector<RID> dynamic_lights;
|
|
LocalVector<RID> dynamic_lights;
|
|
|
|
|
|
|
|
+ PagedArray<InstanceBounds> instance_aabbs;
|
|
|
|
+ PagedArray<InstanceData> instance_data;
|
|
|
|
+
|
|
Scenario() {
|
|
Scenario() {
|
|
indexers[INDEXER_GEOMETRY].set_index(INDEXER_GEOMETRY);
|
|
indexers[INDEXER_GEOMETRY].set_index(INDEXER_GEOMETRY);
|
|
indexers[INDEXER_VOLUMES].set_index(INDEXER_VOLUMES);
|
|
indexers[INDEXER_VOLUMES].set_index(INDEXER_VOLUMES);
|
|
@@ -178,6 +329,7 @@ public:
|
|
RID self;
|
|
RID self;
|
|
//scenario stuff
|
|
//scenario stuff
|
|
DynamicBVH::ID indexer_id;
|
|
DynamicBVH::ID indexer_id;
|
|
|
|
+ int32_t array_index;
|
|
Scenario *scenario;
|
|
Scenario *scenario;
|
|
SelfList<Instance> scenario_item;
|
|
SelfList<Instance> scenario_item;
|
|
|
|
|
|
@@ -199,7 +351,6 @@ public:
|
|
|
|
|
|
Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior
|
|
Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior
|
|
|
|
|
|
- uint64_t last_render_pass;
|
|
|
|
uint64_t last_frame_pass;
|
|
uint64_t last_frame_pass;
|
|
|
|
|
|
uint64_t version; // changes to this, and changes to base increase version
|
|
uint64_t version; // changes to this, and changes to base increase version
|
|
@@ -240,7 +391,6 @@ public:
|
|
lod_begin_hysteresis = 0;
|
|
lod_begin_hysteresis = 0;
|
|
lod_end_hysteresis = 0;
|
|
lod_end_hysteresis = 0;
|
|
|
|
|
|
- last_render_pass = 0;
|
|
|
|
last_frame_pass = 0;
|
|
last_frame_pass = 0;
|
|
version = 1;
|
|
version = 1;
|
|
base_data = nullptr;
|
|
base_data = nullptr;
|
|
@@ -248,6 +398,7 @@ public:
|
|
custom_aabb = nullptr;
|
|
custom_aabb = nullptr;
|
|
|
|
|
|
pair_check = 0;
|
|
pair_check = 0;
|
|
|
|
+ array_index = -1;
|
|
}
|
|
}
|
|
|
|
|
|
~Instance() {
|
|
~Instance() {
|
|
@@ -265,28 +416,17 @@ public:
|
|
|
|
|
|
struct InstanceGeometryData : public InstanceBaseData {
|
|
struct InstanceGeometryData : public InstanceBaseData {
|
|
Set<Instance *> lights;
|
|
Set<Instance *> lights;
|
|
- bool lighting_dirty;
|
|
|
|
bool can_cast_shadows;
|
|
bool can_cast_shadows;
|
|
bool material_is_animated;
|
|
bool material_is_animated;
|
|
|
|
|
|
Set<Instance *> decals;
|
|
Set<Instance *> decals;
|
|
- bool decal_dirty;
|
|
|
|
-
|
|
|
|
Set<Instance *> reflection_probes;
|
|
Set<Instance *> reflection_probes;
|
|
- bool reflection_dirty;
|
|
|
|
-
|
|
|
|
Set<Instance *> gi_probes;
|
|
Set<Instance *> gi_probes;
|
|
- bool gi_probes_dirty;
|
|
|
|
-
|
|
|
|
Set<Instance *> lightmap_captures;
|
|
Set<Instance *> lightmap_captures;
|
|
|
|
|
|
InstanceGeometryData() {
|
|
InstanceGeometryData() {
|
|
- lighting_dirty = false;
|
|
|
|
- reflection_dirty = true;
|
|
|
|
can_cast_shadows = true;
|
|
can_cast_shadows = true;
|
|
material_is_animated = true;
|
|
material_is_animated = true;
|
|
- gi_probes_dirty = true;
|
|
|
|
- decal_dirty = true;
|
|
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
@@ -296,14 +436,12 @@ public:
|
|
Set<Instance *> geometries;
|
|
Set<Instance *> geometries;
|
|
|
|
|
|
RID instance;
|
|
RID instance;
|
|
- bool reflection_dirty;
|
|
|
|
SelfList<InstanceReflectionProbeData> update_list;
|
|
SelfList<InstanceReflectionProbeData> update_list;
|
|
|
|
|
|
int render_step;
|
|
int render_step;
|
|
|
|
|
|
InstanceReflectionProbeData() :
|
|
InstanceReflectionProbeData() :
|
|
update_list(this) {
|
|
update_list(this) {
|
|
- reflection_dirty = true;
|
|
|
|
render_step = -1;
|
|
render_step = -1;
|
|
}
|
|
}
|
|
};
|
|
};
|
|
@@ -334,8 +472,6 @@ public:
|
|
RS::LightBakeMode bake_mode;
|
|
RS::LightBakeMode bake_mode;
|
|
uint32_t max_sdfgi_cascade = 2;
|
|
uint32_t max_sdfgi_cascade = 2;
|
|
|
|
|
|
- uint64_t sdfgi_cascade_light_pass = 0;
|
|
|
|
-
|
|
|
|
InstanceLightData() {
|
|
InstanceLightData() {
|
|
bake_mode = RS::LIGHT_BAKE_DISABLED;
|
|
bake_mode = RS::LIGHT_BAKE_DISABLED;
|
|
shadow_dirty = true;
|
|
shadow_dirty = true;
|
|
@@ -468,25 +604,19 @@ public:
|
|
PagedArrayPool<RID> rid_cull_page_pool;
|
|
PagedArrayPool<RID> rid_cull_page_pool;
|
|
|
|
|
|
PagedArray<Instance *> instance_cull_result;
|
|
PagedArray<Instance *> instance_cull_result;
|
|
|
|
+ PagedArray<RID> mesh_instance_cull_result;
|
|
PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_render;
|
|
PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_render;
|
|
PagedArray<Instance *> instance_shadow_cull_result;
|
|
PagedArray<Instance *> instance_shadow_cull_result;
|
|
PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_shadow_render;
|
|
PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_shadow_render;
|
|
PagedArray<Instance *> instance_sdfgi_cull_result;
|
|
PagedArray<Instance *> instance_sdfgi_cull_result;
|
|
- PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_sdfgi_render;
|
|
|
|
PagedArray<Instance *> light_cull_result;
|
|
PagedArray<Instance *> light_cull_result;
|
|
PagedArray<RendererSceneRender::InstanceBase *> lightmap_cull_result;
|
|
PagedArray<RendererSceneRender::InstanceBase *> lightmap_cull_result;
|
|
- PagedArray<Instance *> directional_shadow_cull_result;
|
|
|
|
PagedArray<RID> reflection_probe_instance_cull_result;
|
|
PagedArray<RID> reflection_probe_instance_cull_result;
|
|
PagedArray<RID> light_instance_cull_result;
|
|
PagedArray<RID> light_instance_cull_result;
|
|
- PagedArray<RID> directional_light_cull_result;
|
|
|
|
|
|
+
|
|
PagedArray<RID> gi_probe_instance_cull_result;
|
|
PagedArray<RID> gi_probe_instance_cull_result;
|
|
PagedArray<RID> decal_instance_cull_result;
|
|
PagedArray<RID> decal_instance_cull_result;
|
|
|
|
|
|
- PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES];
|
|
|
|
-
|
|
|
|
- uint64_t sdfgi_light_cull_pass = 0;
|
|
|
|
- int directional_light_count;
|
|
|
|
-
|
|
|
|
RID_PtrOwner<Instance> instance_owner;
|
|
RID_PtrOwner<Instance> instance_owner;
|
|
|
|
|
|
bool pair_volumes_to_mesh; // used in traditional forward, unnecesary on clustered
|
|
bool pair_volumes_to_mesh; // used in traditional forward, unnecesary on clustered
|
|
@@ -536,10 +666,54 @@ public:
|
|
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
|
|
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
|
|
void _unpair_instance(Instance *p_instance);
|
|
void _unpair_instance(Instance *p_instance);
|
|
|
|
|
|
|
|
+ void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
|
|
|
|
+
|
|
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold);
|
|
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold);
|
|
|
|
|
|
RID _render_get_environment(RID p_camera, RID p_scenario);
|
|
RID _render_get_environment(RID p_camera, RID p_scenario);
|
|
|
|
|
|
|
|
+ struct Cull {
|
|
|
|
+ struct Shadow {
|
|
|
|
+ RID light_instance;
|
|
|
|
+ struct Cascade {
|
|
|
|
+ Frustum frustum;
|
|
|
|
+
|
|
|
|
+ CameraMatrix projection;
|
|
|
|
+ Transform transform;
|
|
|
|
+ real_t zfar;
|
|
|
|
+ real_t split;
|
|
|
|
+ real_t shadow_texel_size;
|
|
|
|
+ real_t bias_scale;
|
|
|
|
+ real_t range_begin;
|
|
|
|
+ Vector2 uv_scale;
|
|
|
|
+
|
|
|
|
+ PagedArray<RendererSceneRender::InstanceBase *> cull_result;
|
|
|
|
+
|
|
|
|
+ } cascades[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES]; //max 4 cascades
|
|
|
|
+ uint32_t cascade_count;
|
|
|
|
+
|
|
|
|
+ } shadows[RendererSceneRender::MAX_DIRECTIONAL_LIGHTS];
|
|
|
|
+
|
|
|
|
+ uint32_t shadow_count;
|
|
|
|
+
|
|
|
|
+ struct SDFGI {
|
|
|
|
+ //have arrays here because SDFGI functions expects this, plus regions can have areas
|
|
|
|
+ PagedArray<RendererSceneRender::InstanceBase *> region_cull_result[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
|
|
|
|
+ AABB region_aabb[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade
|
|
|
|
+ uint32_t region_cascade[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade
|
|
|
|
+ uint32_t region_count = 0;
|
|
|
|
+
|
|
|
|
+ PagedArray<RID> cascade_lights[SDFGI_MAX_CASCADES];
|
|
|
|
+ uint32_t cascade_light_index[SDFGI_MAX_CASCADES];
|
|
|
|
+ uint32_t cascade_light_count = 0;
|
|
|
|
+
|
|
|
|
+ } sdfgi;
|
|
|
|
+
|
|
|
|
+ SpinLock lock;
|
|
|
|
+
|
|
|
|
+ Frustum frustum;
|
|
|
|
+ } cull;
|
|
|
|
+
|
|
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
|
|
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
|
|
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows = true);
|
|
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows = true);
|
|
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
|
|
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
|