summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/rasterizer_dummy.h53
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp164
-rw-r--r--servers/rendering/renderer_canvas_cull.h36
-rw-r--r--servers/rendering/renderer_canvas_render.h14
-rw-r--r--servers/rendering/renderer_compositor.cpp9
-rw-r--r--servers/rendering/renderer_compositor.h47
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp96
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h25
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp14
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h83
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp28
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp54
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h101
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp72
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h7
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp7
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h9
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp20
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp7
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp81
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h205
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp151
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h115
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp198
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h60
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/gi.glsl27
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl3
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl36
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl13
-rw-r--r--servers/rendering/renderer_rd/shaders/sky.glsl31
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl35
-rw-r--r--servers/rendering/renderer_scene.h14
-rw-r--r--servers/rendering/renderer_scene_cull.cpp999
-rw-r--r--servers/rendering/renderer_scene_cull.h126
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.cpp4
-rw-r--r--servers/rendering/renderer_scene_render.cpp150
-rw-r--r--servers/rendering/renderer_scene_render.h24
-rw-r--r--servers/rendering/renderer_storage.h41
-rw-r--r--servers/rendering/renderer_viewport.cpp158
-rw-r--r--servers/rendering/renderer_viewport.h20
-rw-r--r--servers/rendering/rendering_device.cpp74
-rw-r--r--servers/rendering/rendering_device.h34
-rw-r--r--servers/rendering/rendering_device_binds.cpp4
-rw-r--r--servers/rendering/rendering_device_binds.h76
-rw-r--r--servers/rendering/rendering_server_default.cpp32
-rw-r--r--servers/rendering/rendering_server_default.h75
-rw-r--r--servers/rendering/rendering_server_globals.cpp2
-rw-r--r--servers/rendering/rendering_server_globals.h2
-rw-r--r--servers/rendering/shader_language.cpp2
-rw-r--r--servers/rendering/shader_language.h2
-rw-r--r--servers/rendering/shader_types.cpp8
58 files changed, 2310 insertions, 1359 deletions
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index 96c9137c6e..3d4cca3586 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -175,7 +175,7 @@ public:
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
- void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) override {}
+ void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) override {}
void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
@@ -184,7 +184,7 @@ public:
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) override {}
+ void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override {}
void gi_set_use_half_resolution(bool p_enable) override {}
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
@@ -225,7 +225,6 @@ public:
}
void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {}
- void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override {}
void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override {}
@@ -324,7 +323,9 @@ public:
void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
- void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
@@ -365,23 +366,6 @@ public:
void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
- /* IMMEDIATE API */
-
- RID immediate_allocate() override { return RID(); }
- void immediate_initialize(RID p_rid) override {}
- void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) override {}
- void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) override {}
- void immediate_normal(RID p_immediate, const Vector3 &p_normal) override {}
- void immediate_tangent(RID p_immediate, const Plane &p_tangent) override {}
- void immediate_color(RID p_immediate, const Color &p_color) override {}
- void immediate_uv(RID p_immediate, const Vector2 &tex_uv) override {}
- void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) override {}
- void immediate_end(RID p_immediate) override {}
- void immediate_clear(RID p_immediate) override {}
- void immediate_set_material(RID p_immediate, RID p_material) override {}
- RID immediate_get_material(RID p_immediate) const override { return RID(); }
- AABB immediate_get_aabb(RID p_immediate) const override { return AABB(); }
-
/* SKELETON API */
RID skeleton_allocate() override { return RID(); }
@@ -421,10 +405,8 @@ public:
void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
bool light_directional_get_blend_splits(RID p_light) const override { return false; }
- void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) override {}
void light_directional_set_sky_only(RID p_light, bool p_sky_only) override {}
bool light_directional_is_sky_only(RID p_light) const override { return false; }
- RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; }
RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
@@ -506,12 +488,6 @@ public:
void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {}
float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; }
- void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) override {}
- float voxel_gi_get_ao(RID p_voxel_gi) const override { return 0; }
-
- void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) override {}
- float voxel_gi_get_ao_size(RID p_voxel_gi) const override { return 0; }
-
void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {}
float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; }
@@ -621,9 +597,18 @@ public:
bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
- RID particles_collision_instance_create(RID p_collision) override { return RID(); };
- void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override{};
- void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override{};
+ RID particles_collision_instance_create(RID p_collision) override { return RID(); }
+ void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
+ void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
+
+ /* VISIBILITY NOTIFIER */
+ virtual RID visibility_notifier_allocate() override { return RID(); }
+ virtual void visibility_notifier_initialize(RID p_notifier) override {}
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {}
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {}
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
/* GLOBAL VARIABLES */
@@ -649,7 +634,7 @@ public:
RID render_target_create() override { return RID(); }
void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
- void render_target_set_size(RID p_render_target, int p_width, int p_height) override {}
+ void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
RID render_target_get_texture(RID p_render_target) override { return RID(); }
void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
@@ -725,8 +710,6 @@ public:
void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) override {}
void set_shadow_texture_size(int p_size) override {}
- void draw_window_margins(int *p_margins, RID *p_margin_textures) override {}
-
bool free(RID p_rid) override { return true; }
void update() override {}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 6e126ea77e..ec0a8347f8 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -97,14 +97,14 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
}
}
-void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<RendererCanvasCull::Item, true> &canvas_item_owner) {
+void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_Owner<RendererCanvasCull::Item, true> &canvas_item_owner) {
do {
ysort_owner->ysort_children_count = -1;
ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : nullptr;
} while (ysort_owner && ysort_owner->sort_y);
}
-void _attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from) {
+void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform) {
if (ci->copy_back_buffer) {
ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect);
}
@@ -173,32 +173,44 @@ void _attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCu
}
}
- if (ci->update_when_visible) {
- RenderingServerDefault::redraw_request();
- }
-
- if ((ci->commands != nullptr && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {
+ if (((ci->commands != nullptr || ci->visibility_notifier) && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {
//something to draw?
- ci->final_transform = xform;
- ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a);
- ci->global_rect_cache = global_rect;
- ci->global_rect_cache.position -= p_clip_rect.position;
- ci->light_masked = false;
- int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
+ if (ci->update_when_visible) {
+ RenderingServerDefault::redraw_request();
+ }
- if (z_last_list[zidx]) {
- z_last_list[zidx]->next = ci;
- z_last_list[zidx] = ci;
+ if (ci->commands != nullptr) {
+ ci->final_transform = xform;
+ ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a);
+ ci->global_rect_cache = global_rect;
+ ci->global_rect_cache.position -= p_clip_rect.position;
+ ci->light_masked = false;
- } else {
- z_list[zidx] = ci;
- z_last_list[zidx] = ci;
+ int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
+
+ if (z_last_list[zidx]) {
+ z_last_list[zidx]->next = ci;
+ z_last_list[zidx] = ci;
+
+ } else {
+ z_list[zidx] = ci;
+ z_last_list[zidx] = ci;
+ }
+
+ ci->z_final = p_z;
+
+ ci->next = nullptr;
}
- ci->z_final = p_z;
+ if (ci->visibility_notifier) {
+ if (!ci->visibility_notifier->visible_element.in_list()) {
+ visibility_notifier_list.add(&ci->visibility_notifier->visible_element);
+ ci->visibility_notifier->just_visible = true;
+ }
- ci->next = nullptr;
+ ci->visibility_notifier->visible_in_frame = RSG::rasterizer->get_frame_number();
+ }
}
}
@@ -215,6 +227,13 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
}
Rect2 rect = ci->get_rect();
+
+ if (ci->visibility_notifier) {
+ if (ci->visibility_notifier->area.size != Vector2()) {
+ rect = rect.merge(ci->visibility_notifier->area);
+ }
+ }
+
Transform2D xform = ci->xform;
if (snapping_2d_transforms_to_pixel) {
xform.elements[2] = xform.elements[2].floor();
@@ -289,7 +308,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
canvas_group_from = z_last_list[zidx];
}
- _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;
@@ -305,7 +324,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
}
_cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
}
- _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform);
for (int i = 0; i < child_item_count; i++) {
if (child_items[i]->behind || use_canvas_group) {
continue;
@@ -373,8 +392,7 @@ RID RendererCanvasCull::canvas_allocate() {
return canvas_owner.allocate_rid();
}
void RendererCanvasCull::canvas_initialize(RID p_rid) {
- Canvas *canvas = memnew(Canvas);
- canvas_owner.initialize_rid(p_rid, canvas);
+ canvas_owner.initialize_rid(p_rid);
}
void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) {
@@ -410,8 +428,7 @@ RID RendererCanvasCull::canvas_item_allocate() {
return canvas_item_owner.allocate_rid();
}
void RendererCanvasCull::canvas_item_initialize(RID p_rid) {
- Item *canvas_item = memnew(Item);
- canvas_item_owner.initialize_rid(p_rid, canvas_item);
+ canvas_item_owner.initialize_rid(p_rid);
}
void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {
@@ -984,6 +1001,18 @@ void RendererCanvasCull::canvas_item_add_clip_ignore(RID p_item, bool p_ignore)
ci->ignore = p_ignore;
}
+void RendererCanvasCull::canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) {
+ Item *canvas_item = canvas_item_owner.getornull(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandAnimationSlice *as = canvas_item->alloc_command<Item::CommandAnimationSlice>();
+ ERR_FAIL_COND(!as);
+ as->animation_length = p_animation_length;
+ as->slice_begin = p_slice_begin;
+ as->slice_end = p_slice_end;
+ as->offset = p_offset;
+}
+
void RendererCanvasCull::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1095,6 +1124,26 @@ void RendererCanvasCull::canvas_item_set_use_parent_material(RID p_item, bool p_
canvas_item->use_parent_material = p_enable;
}
+void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable) {
+ Item *canvas_item = canvas_item_owner.getornull(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ if (p_enable) {
+ if (!canvas_item->visibility_notifier) {
+ canvas_item->visibility_notifier = visibility_notifier_allocator.alloc();
+ }
+ canvas_item->visibility_notifier->area = p_area;
+ canvas_item->visibility_notifier->enter_callable = p_enter_callable;
+ canvas_item->visibility_notifier->exit_callable = p_exit_callable;
+
+ } else {
+ if (canvas_item->visibility_notifier) {
+ visibility_notifier_allocator.free(canvas_item->visibility_notifier);
+ canvas_item->visibility_notifier = nullptr;
+ }
+ }
+}
+
void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1120,9 +1169,9 @@ RID RendererCanvasCull::canvas_light_allocate() {
return canvas_light_owner.allocate_rid();
}
void RendererCanvasCull::canvas_light_initialize(RID p_rid) {
- RendererCanvasRender::Light *clight = memnew(RendererCanvasRender::Light);
+ canvas_light_owner.initialize_rid(p_rid);
+ RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_rid);
clight->light_internal = RSG::canvas_render->light_create();
- return canvas_light_owner.initialize_rid(p_rid, clight);
}
void RendererCanvasCull::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {
@@ -1316,9 +1365,7 @@ RID RendererCanvasCull::canvas_light_occluder_allocate() {
return canvas_light_occluder_owner.allocate_rid();
}
void RendererCanvasCull::canvas_light_occluder_initialize(RID p_rid) {
- RendererCanvasRender::LightOccluderInstance *occluder = memnew(RendererCanvasRender::LightOccluderInstance);
-
- return canvas_light_occluder_owner.initialize_rid(p_rid, occluder);
+ return canvas_light_occluder_owner.initialize_rid(p_rid);
}
void RendererCanvasCull::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {
@@ -1400,9 +1447,9 @@ RID RendererCanvasCull::canvas_occluder_polygon_allocate() {
return canvas_light_occluder_polygon_owner.allocate_rid();
}
void RendererCanvasCull::canvas_occluder_polygon_initialize(RID p_rid) {
- LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon);
+ canvas_light_occluder_polygon_owner.initialize_rid(p_rid);
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid);
occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create();
- return canvas_light_occluder_polygon_owner.initialize_rid(p_rid, occluder_poly);
}
void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {
@@ -1477,6 +1524,44 @@ void RendererCanvasCull::canvas_item_set_default_texture_repeat(RID p_item, RS::
ci->texture_repeat = p_repeat;
}
+void RendererCanvasCull::update_visibility_notifiers() {
+ SelfList<Item::VisibilityNotifierData> *E = visibility_notifier_list.first();
+ while (E) {
+ SelfList<Item::VisibilityNotifierData> *N = E->next();
+
+ Item::VisibilityNotifierData *visibility_notifier = E->self();
+ if (visibility_notifier->just_visible) {
+ visibility_notifier->just_visible = false;
+
+ if (!visibility_notifier->enter_callable.is_null()) {
+ if (RSG::threaded) {
+ visibility_notifier->enter_callable.call_deferred(nullptr, 0);
+ } else {
+ Callable::CallError ce;
+ Variant ret;
+ visibility_notifier->enter_callable.call(nullptr, 0, ret, ce);
+ }
+ }
+ } else {
+ if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {
+ visibility_notifier_list.remove(E);
+
+ if (!visibility_notifier->exit_callable.is_null()) {
+ if (RSG::threaded) {
+ visibility_notifier->exit_callable.call_deferred(nullptr, 0);
+ } else {
+ Callable::CallError ce;
+ Variant ret;
+ visibility_notifier->exit_callable.call(nullptr, 0, ret, ce);
+ }
+ }
+ }
+ }
+
+ E = N;
+ }
+}
+
bool RendererCanvasCull::free(RID p_rid) {
if (canvas_owner.owns(p_rid)) {
Canvas *canvas = canvas_owner.getornull(p_rid);
@@ -1507,8 +1592,6 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_owner.free(p_rid);
- memdelete(canvas);
-
} else if (canvas_item_owner.owns(p_rid)) {
Item *canvas_item = canvas_item_owner.getornull(p_rid);
ERR_FAIL_COND_V(!canvas_item, true);
@@ -1531,6 +1614,10 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_item->child_items[i]->parent = RID();
}
+ if (canvas_item->visibility_notifier != nullptr) {
+ visibility_notifier_allocator.free(canvas_item->visibility_notifier);
+ }
+
/*
if (canvas_item->material) {
canvas_item->material->owners.erase(canvas_item);
@@ -1539,8 +1626,6 @@ bool RendererCanvasCull::free(RID p_rid) {
canvas_item_owner.free(p_rid);
- memdelete(canvas_item);
-
} else if (canvas_light_owner.owns(p_rid)) {
RendererCanvasRender::Light *canvas_light = canvas_light_owner.getornull(p_rid);
ERR_FAIL_COND_V(!canvas_light, true);
@@ -1555,7 +1640,6 @@ bool RendererCanvasCull::free(RID p_rid) {
RSG::canvas_render->free(canvas_light->light_internal);
canvas_light_owner.free(p_rid);
- memdelete(canvas_light);
} else if (canvas_light_occluder_owner.owns(p_rid)) {
RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_rid);
@@ -1574,7 +1658,6 @@ bool RendererCanvasCull::free(RID p_rid) {
}
canvas_light_occluder_owner.free(p_rid);
- memdelete(occluder);
} else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid);
@@ -1587,7 +1670,6 @@ bool RendererCanvasCull::free(RID p_rid) {
}
canvas_light_occluder_polygon_owner.free(p_rid);
- memdelete(occluder_poly);
} else {
return false;
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 37391d7c0e..79b5450d14 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -31,6 +31,7 @@
#ifndef RENDERING_SERVER_CANVAS_CULL_H
#define RENDERING_SERVER_CANVAS_CULL_H
+#include "core/templates/paged_allocator.h"
#include "renderer_compositor.h"
#include "renderer_viewport.h"
@@ -55,6 +56,20 @@ public:
Vector<Item *> child_items;
+ struct VisibilityNotifierData {
+ Rect2 area;
+ Callable enter_callable;
+ Callable exit_callable;
+ bool just_visible = false;
+ uint64_t visible_in_frame = 0;
+ SelfList<VisibilityNotifierData> visible_element;
+ VisibilityNotifierData() :
+ visible_element(this) {
+ }
+ };
+
+ VisibilityNotifierData *visibility_notifier = nullptr;
+
Item() {
children_order_dirty = true;
E = nullptr;
@@ -101,9 +116,9 @@ public:
}
};
- RID_PtrOwner<LightOccluderPolygon, true> canvas_light_occluder_polygon_owner;
+ RID_Owner<LightOccluderPolygon, true> canvas_light_occluder_polygon_owner;
- RID_PtrOwner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner;
+ RID_Owner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner;
struct Canvas : public RendererViewport::CanvasBase {
Set<RID> viewports;
@@ -148,14 +163,19 @@ public:
}
};
- mutable RID_PtrOwner<Canvas, true> canvas_owner;
- RID_PtrOwner<Item, true> canvas_item_owner;
- RID_PtrOwner<RendererCanvasRender::Light, true> canvas_light_owner;
+ mutable RID_Owner<Canvas, true> canvas_owner;
+ RID_Owner<Item, true> canvas_item_owner;
+ RID_Owner<RendererCanvasRender::Light, true> canvas_light_owner;
bool disable_scale;
bool sdf_used = false;
bool snapping_2d_transforms_to_pixel = false;
+ PagedAllocator<Item::VisibilityNotifierData> visibility_notifier_allocator;
+ SelfList<Item::VisibilityNotifierData>::List visibility_notifier_list;
+
+ _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform);
+
private:
void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel);
void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort);
@@ -211,6 +231,8 @@ public:
void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture);
void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);
void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
+ void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset);
+
void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
void canvas_item_set_z_index(RID p_item, int p_z);
void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
@@ -224,6 +246,8 @@ public:
void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
+ void canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable);
+
void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false);
RID canvas_light_allocate();
@@ -283,6 +307,8 @@ public:
void canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter);
void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat);
+ void update_visibility_notifiers();
+
bool free(RID p_rid);
RendererCanvasCull();
~RendererCanvasCull();
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 0266e137c0..8afe9ef410 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -180,6 +180,7 @@ public:
TYPE_PARTICLES,
TYPE_TRANSFORM,
TYPE_CLIP_IGNORE,
+ TYPE_ANIMATION_SLICE,
};
Command *next;
@@ -286,6 +287,17 @@ public:
}
};
+ struct CommandAnimationSlice : public Command {
+ double animation_length = 0;
+ double slice_begin = 0;
+ double slice_end = 0;
+ double offset = 0;
+
+ CommandAnimationSlice() {
+ type = TYPE_ANIMATION_SLICE;
+ }
+ };
+
struct ViewportRender {
RenderingServer *owner;
void *udata;
@@ -596,8 +608,6 @@ public:
virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0;
virtual void set_shadow_texture_size(int p_size) = 0;
- virtual void draw_window_margins(int *p_margins, RID *p_margin_textures) = 0;
-
virtual bool free(RID p_rid) = 0;
virtual void update() = 0;
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index 8861522d34..80c4625261 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -30,6 +30,7 @@
#include "renderer_compositor.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -39,4 +40,12 @@ RendererCompositor *RendererCompositor::create() {
return _create_func();
}
+bool RendererCompositor::is_xr_enabled() const {
+ return xr_enabled;
+}
+
+RendererCompositor::RendererCompositor() {
+ xr_enabled = GLOBAL_GET("rendering/xr/enabled");
+}
+
RendererCanvasRender *RendererCanvasRender::singleton = nullptr;
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 41aaba0f4c..eabdebf4b3 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -40,7 +40,31 @@
#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
+struct BlitToScreen {
+ RID render_target;
+ Rect2i rect;
+
+ struct {
+ bool use_layer = false;
+ uint32_t layer = 0;
+ } multi_view;
+
+ struct {
+ //lens distorted parameters for VR
+ bool apply = false;
+ Vector2 eye_center;
+ float k1 = 0.0;
+ float k2 = 0.0;
+
+ float upscale = 1.0;
+ float aspect_ratio = 1.0;
+ } lens_distortion;
+};
+
class RendererCompositor {
+private:
+ bool xr_enabled = false;
+
protected:
static RendererCompositor *(*_create_func)();
@@ -56,27 +80,6 @@ public:
virtual void initialize() = 0;
virtual void begin_frame(double frame_step) = 0;
- struct BlitToScreen {
- RID render_target;
- Rect2i rect;
-
- struct {
- bool use_layer = false;
- uint32_t layer = 0;
- } multi_view;
-
- struct {
- //lens distorted parameters for VR
- bool apply = false;
- Vector2 eye_center;
- float k1 = 0.0;
- float k2 = 0.0;
-
- float upscale = 1.0;
- float aspect_ratio = 1.0;
- } lens_distortion;
- };
-
virtual void prepare_for_blitting_render_targets() = 0;
virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0;
@@ -86,7 +89,9 @@ public:
virtual float get_frame_delta_time() const = 0;
virtual bool is_low_end() const = 0;
+ virtual bool is_xr_enabled() const;
+ RendererCompositor();
virtual ~RendererCompositor() {}
};
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 872f7b5beb..4290e0d574 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -34,23 +34,9 @@
#include "core/math/math_defs.h"
#include "core/os/os.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "thirdparty/misc/cubemap_coeffs.h"
-static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) {
- p_array[0] = p_basis.elements[0][0];
- p_array[1] = p_basis.elements[1][0];
- p_array[2] = p_basis.elements[2][0];
- p_array[3] = 0;
- p_array[4] = p_basis.elements[0][1];
- p_array[5] = p_basis.elements[1][1];
- p_array[6] = p_basis.elements[2][1];
- p_array[7] = 0;
- p_array[8] = p_basis.elements[0][2];
- p_array[9] = p_basis.elements[1][2];
- p_array[10] = p_basis.elements[2][2];
- p_array[11] = 0;
-}
-
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
@@ -732,6 +718,11 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x;
tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y;
+ if (p_settings.view_count > 1) {
+ // Use MULTIVIEW versions
+ mode += 4;
+ }
+
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0);
@@ -934,10 +925,10 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, ssao.gather_uniform_set, 0);
+void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, ssao.importance_map_uniform_set, 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
}
for (int i = 0; i < 4; i++) {
@@ -960,7 +951,7 @@ void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
}
-void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &p_depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets) {
+void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &p_depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_downsample_uniform_set, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->draw_command_begin_label("SSAO");
/* FIRST PASS */
@@ -990,7 +981,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
u.ids.push_back(p_depth_mipmaps[3]);
uniforms.push_back(u);
}
- ssao.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, 2), 2);
+ r_downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, 2), 2);
}
float depth_linearize_mul = -p_projection.matrix[3][2];
@@ -1025,7 +1016,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[0]), 1);
if (p_settings.quality > RS::ENV_SSAO_QUALITY_MEDIUM) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.downsample_uniform_set, 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, r_downsample_uniform_set, 2);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.downsample_push_constant, sizeof(SSAODownsamplePushConstant));
@@ -1109,7 +1100,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
u.ids.push_back(ssao.gather_constants_buffer);
uniforms.push_back(u);
}
- ssao.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
+ r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
}
if (p_invalidate_uniform_sets) {
@@ -1136,7 +1127,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
u.ids.push_back(ssao.importance_map_load_counter);
uniforms.push_back(u);
}
- ssao.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
+ r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
}
if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
@@ -1147,7 +1138,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
ssao.importance_map_push_constant.power = p_settings.power;
//base pass
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
- gather_ssao(compute_list, p_ao_pong_slices, p_settings, true);
+ gather_ssao(compute_list, p_ao_pong_slices, p_settings, true, r_gather_uniform_set, RID());
//generate importance map
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
@@ -1178,7 +1169,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
}
- gather_ssao(compute_list, p_ao_slices, p_settings, false);
+ gather_ssao(compute_list, p_ao_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set);
RD::get_singleton()->draw_command_end_label(); // Gather SSAO
}
@@ -1365,42 +1356,6 @@ void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap,
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
- SkyPushConstant sky_push_constant;
-
- memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
-
- sky_push_constant.proj[0] = p_camera.matrix[2][0];
- sky_push_constant.proj[1] = p_camera.matrix[0][0];
- sky_push_constant.proj[2] = p_camera.matrix[2][1];
- sky_push_constant.proj[3] = p_camera.matrix[1][1];
- sky_push_constant.position[0] = p_position.x;
- sky_push_constant.position[1] = p_position.y;
- sky_push_constant.position[2] = p_position.z;
- sky_push_constant.multiplier = p_multiplier;
- sky_push_constant.time = p_time;
- store_transform_3x3(p_orientation, sky_push_constant.orientation);
-
- RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
-
- RD::DrawListID draw_list = p_list;
-
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_samplers, 0);
- if (p_uniform_set.is_valid()) { //material may not have uniform set
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
- }
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_fog, 3);
-
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
-}
-
void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
ResolvePushConstant push_constant;
push_constant.screen_size[0] = p_screen_size.x;
@@ -1553,12 +1508,29 @@ EffectsRD::EffectsRD() {
tonemap_modes.push_back("\n#define USE_1D_LUT\n");
tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
+ // multiview versions of our shaders
+ tonemap_modes.push_back("\n#define MULTIVIEW\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_1D_LUT\n");
+ tonemap_modes.push_back("\n#define MULTIVIEW\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n");
+
tonemap.shader.initialize(tonemap_modes);
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_NORMAL_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_1D_LUT_MULTIVIEW, false);
+ tonemap.shader.set_variant_enabled(TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW, false);
+ }
+
tonemap.shader_version = tonemap.shader.version_create();
for (int i = 0; i < TONEMAP_MODE_MAX; i++) {
- tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ if (tonemap.shader.is_variant_enabled(i)) {
+ tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ tonemap.pipelines[i].clear();
+ }
}
}
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index ab0100f8f9..b4ddd400a8 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -55,6 +55,7 @@
#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/tonemap.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
@@ -170,6 +171,12 @@ class EffectsRD {
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
TONEMAP_MODE_1D_LUT,
TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT,
+
+ TONEMAP_MODE_NORMAL_MULTIVIEW,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER_MULTIVIEW,
+ TONEMAP_MODE_1D_LUT_MULTIVIEW,
+ TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT_MULTIVIEW,
+
TONEMAP_MODE_MAX
};
@@ -378,12 +385,10 @@ class EffectsRD {
SSAODownsamplePushConstant downsample_push_constant;
SsaoDownsampleShaderRD downsample_shader;
RID downsample_shader_version;
- RID downsample_uniform_set;
SSAOGatherPushConstant gather_push_constant;
SsaoShaderRD gather_shader;
RID gather_shader_version;
- RID gather_uniform_set;
RID gather_constants_buffer;
bool gather_initialized = false;
@@ -391,7 +396,6 @@ class EffectsRD {
SsaoImportanceMapShaderRD importance_map_shader;
RID importance_map_shader_version;
RID importance_map_load_counter;
- RID importance_map_uniform_set;
RID counter_uniform_set;
SSAOBlurPushConstant blur_push_constant;
@@ -452,15 +456,6 @@ class EffectsRD {
} filter;
- struct SkyPushConstant {
- float orientation[12];
- float proj[4];
- float position[3];
- float multiplier;
- float time;
- float pad[3];
- };
-
enum SpecularMergeMode {
SPECULAR_MERGE_ADD,
SPECULAR_MERGE_SSR,
@@ -714,6 +709,7 @@ public:
bool use_fxaa = false;
bool use_debanding = false;
Vector2i texture_size;
+ uint32_t view_count = 1;
};
struct SSAOSettings {
@@ -738,13 +734,12 @@ public:
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
- void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass);
- void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets);
+ void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
+ void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_downsample_uniform_set, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
- void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index e1c2836f6c..b66b9b597c 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -183,9 +183,11 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
}
}
-void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) {
+void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
clear();
+ ERR_FAIL_COND_MSG(p_view_count != 1, "Multiple views is currently not supported in this renderer, please use the mobile renderer for VR support");
+
msaa = p_msaa;
width = p_width;
@@ -901,6 +903,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
uint32_t flags = inst->base_flags; //fill flags if appropriate
+ if (inst->non_uniform_scale) {
+ flags |= INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE;
+ }
bool uses_lightmap = false;
bool uses_gi = false;
@@ -1091,6 +1096,8 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
}
void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
+ ERR_FAIL_COND_MSG(p_render_data->view_count != 1, "Multiview is currently not supported in the clustered renderer. Please use the mobile renderer for VR.");
+
RenderBufferDataForwardClustered *render_buffer = nullptr;
if (p_render_data->render_buffers.is_valid()) {
render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers);
@@ -1431,7 +1438,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
projection = correction * p_render_data->cam_projection;
}
RD::get_singleton()->draw_command_begin_label("Draw Sky");
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_render_data->cam_transform, time);
+ sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
RD::get_singleton()->draw_command_end_label();
}
@@ -2590,6 +2597,8 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
//Fill push constant
+ ginstance->base_flags = 0;
+
bool store_transform = true;
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
@@ -2733,6 +2742,7 @@ void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p
float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
+
ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
ginstance->lod_model_scale = max_scale;
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index e276e55de2..97b7124cc1 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -103,12 +103,12 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void ensure_specular();
void ensure_voxelgi();
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
~RenderBufferDataForwardClustered();
};
- virtual RenderBufferData *_create_render_buffer_data();
+ virtual RenderBufferData *_create_render_buffer_data() override;
void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb);
RID render_base_uniform_set;
@@ -117,8 +117,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
- virtual void _base_uniforms_changed();
- virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
+ virtual void _base_uniforms_changed() override;
+ virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
@@ -184,6 +184,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
};
enum {
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
@@ -196,7 +197,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 24,
};
struct SceneState {
@@ -204,7 +204,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
-
float camera_matrix[16];
float inv_camera_matrix[16];
@@ -566,46 +565,46 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RenderList render_list[RENDER_LIST_MAX];
protected:
- virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color);
+ virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
- virtual void _render_shadow_begin();
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
- virtual void _render_shadow_process();
- virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ virtual void _render_shadow_begin() override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true) override;
+ virtual void _render_shadow_process() override;
+ virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
public:
- virtual GeometryInstance *geometry_instance_create(RID p_base);
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton);
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index);
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9);
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance);
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
-
- virtual uint32_t geometry_instance_get_pair_mask();
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count);
-
- virtual bool free(RID p_rid);
+ virtual GeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
+ virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
+ virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
+ virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
+ virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
+ virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
+ virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
+ virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
+ virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
+
+ virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
+ virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
+
+ virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+
+ virtual uint32_t geometry_instance_get_pair_mask() override;
+ virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
+ virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
+ virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
+ virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
+
+ virtual bool free(RID p_rid) override;
RenderForwardClustered(RendererStorageRD *p_storage);
~RenderForwardClustered();
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index dcfdf14784..f125931df8 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -560,17 +560,18 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
{
Vector<String> shader_versions;
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n");
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n");
- shader_versions.push_back("");
- shader_versions.push_back("\n#define USE_FORWARD_GI\n");
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n");
- shader_versions.push_back("\n#define USE_LIGHTMAP\n");
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n");
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_DEPTH_PASS_DP
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
+ shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
+ shader_versions.push_back("\n#define USE_FORWARD_GI\n"); // SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI
+ shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR
+ shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
+ shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR
+
shader.initialize(shader_versions, p_defines);
}
@@ -656,6 +657,11 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ // not implemented but need these just in case code is in the shaders
+ actions.renames["VIEW_INDEX"] = "0";
+ actions.renames["VIEW_MONO_LEFT"] = "0";
+ actions.renames["VIEW_RIGHT"] = "1";
+
//for light
actions.renames["VIEW"] = "view";
actions.renames["LIGHT_COLOR"] = "light_color";
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 6845133825..8add9f8095 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -56,6 +56,7 @@ public:
SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
+
SHADER_VERSION_MAX
};
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 370d8eca4e..fdcf4394a7 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -53,13 +53,14 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
color_fb = RID();
}
-void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) {
+void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
clear();
msaa = p_msaa;
width = p_width;
height = p_height;
+ view_count = p_view_count;
color = p_color_buffer;
depth = p_depth_buffer;
@@ -71,13 +72,18 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
fb.push_back(p_color_buffer);
fb.push_back(depth);
- color_fb = RD::get_singleton()->framebuffer_create(fb);
+ color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
} else {
RD::TextureFormat tf;
+ if (view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else {
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ }
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = p_width;
tf.height = p_height;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
@@ -103,7 +109,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
fb.push_back(color_msaa);
fb.push_back(depth_msaa);
- color_fb = RD::get_singleton()->framebuffer_create(fb);
+ color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
}
}
@@ -479,7 +485,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Vector<Color> c;
c.push_back(clear_color.to_linear());
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
}
@@ -488,14 +494,16 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (draw_sky || draw_sky_fog_only) {
RENDER_TIMESTAMP("Render Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ RD::get_singleton()->draw_command_begin_label("Draw Sky");
+
if (p_render_data->reflection_probe.is_valid()) {
CameraMatrix correction;
correction.set_depth_correction(true);
- projection = correction * p_render_data->cam_projection;
+ CameraMatrix projection = correction * p_render_data->cam_projection;
+ sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ } else {
+ sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
}
- RD::get_singleton()->draw_command_begin_label("Draw Sky");
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_render_data->cam_transform, time);
RD::get_singleton()->draw_command_end_label();
}
@@ -522,7 +530,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
@@ -555,6 +563,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
RenderDataRD render_data;
render_data.cam_projection = p_projection;
render_data.cam_transform = p_transform;
+ render_data.view_projection[0] = p_projection;
render_data.z_near = 0.0;
render_data.z_far = p_zfar;
render_data.instances = &p_instances;
@@ -622,7 +631,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -647,6 +656,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
render_data.cam_transform = p_cam_transform;
+ render_data.view_projection[0] = p_cam_projection;
render_data.instances = &p_instances;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -757,6 +767,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
render_data.cam_transform = p_cam_transform;
+ render_data.view_projection[0] = p_cam_projection;
render_data.z_near = 0.0;
render_data.z_far = p_cam_projection.get_z_far();
render_data.instances = &p_instances;
@@ -952,6 +963,10 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
uint32_t flags = inst->base_flags; //fill flags if appropriate
+ if (inst->non_uniform_scale) {
+ flags |= INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE;
+ }
+
bool uses_lightmap = false;
// bool uses_gi = false;
@@ -1089,6 +1104,12 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix);
RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
+ for (uint32_t v = 0; v < p_render_data->view_count; v++) {
+ projection = correction * p_render_data->view_projection[v];
+ RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
+ RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
+ }
+
scene_state.ubo.z_far = p_render_data->z_far;
scene_state.ubo.z_near = p_render_data->z_near;
@@ -1426,18 +1447,20 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
case PASS_MODE_COLOR:
case PASS_MODE_COLOR_TRANSPARENT: {
if (element_info.uses_lightmap) {
- shader_version = SceneShaderForwardMobile::SHADER_VERSION_LIGHTMAP_COLOR_PASS;
+ shader_version = p_params->view_count > 1 ? SceneShaderForwardMobile::SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW : SceneShaderForwardMobile::SHADER_VERSION_LIGHTMAP_COLOR_PASS;
} else {
- shader_version = SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS;
+ shader_version = p_params->view_count > 1 ? SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS_MULTIVIEW : SceneShaderForwardMobile::SHADER_VERSION_COLOR_PASS;
}
} break;
case PASS_MODE_SHADOW: {
- shader_version = SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS;
+ shader_version = p_params->view_count > 1 ? SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS_MULTIVIEW : SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS;
} break;
case PASS_MODE_SHADOW_DP: {
- shader_version = SceneShaderForwardMobile::SHADER_VERSION_DEPTH_PASS_DP;
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass");
+ shader_version = SceneShaderForwardMobile::SHADER_VERSION_SHADOW_PASS_DP;
} break;
case PASS_MODE_DEPTH_MATERIAL: {
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass");
shader_version = SceneShaderForwardMobile::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL;
} break;
}
@@ -1976,6 +1999,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
//Fill push constant
bool store_transform = true;
+ ginstance->base_flags = 0;
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index a2189693d0..b51a58295d 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -85,14 +85,15 @@ protected:
RID color_fb;
int width, height;
+ uint32_t view_count;
void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa);
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
~RenderBufferDataForwardMobile();
};
- virtual RenderBufferData *_create_render_buffer_data();
+ virtual RenderBufferData *_create_render_buffer_data() override;
/* Rendering */
@@ -120,6 +121,7 @@ protected:
bool reverse_cull = false;
PassMode pass_mode = PASS_MODE_COLOR;
// bool no_gi = false;
+ uint32_t view_count = 1;
RID render_pass_uniform_set;
bool force_wireframe = false;
Vector2 uv_offset;
@@ -130,13 +132,14 @@ protected:
uint32_t element_offset = 0;
uint32_t barrier = RD::BARRIER_MASK_ALL;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
reverse_cull = p_reverse_cull;
pass_mode = p_pass_mode;
// no_gi = p_no_gi;
+ view_count = p_view_count;
render_pass_uniform_set = p_render_pass_uniform_set;
force_wireframe = p_force_wireframe;
uv_offset = p_uv_offset;
@@ -149,23 +152,23 @@ protected:
};
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
- virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color);
+ virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
- virtual void _render_shadow_begin();
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
- virtual void _render_shadow_process();
- virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ virtual void _render_shadow_begin() override;
+ virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true) override;
+ virtual void _render_shadow_process() override;
+ virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
+ virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
- virtual void _base_uniforms_changed();
+ virtual void _base_uniforms_changed() override;
void _update_render_base_uniform_set();
- virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
+ virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
@@ -196,10 +199,12 @@ protected:
struct UBO {
float projection_matrix[16];
float inv_projection_matrix[16];
-
float camera_matrix[16];
float inv_camera_matrix[16];
+ float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+ float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+
float viewport_size[2];
float screen_pixel_size[2];
@@ -385,6 +390,7 @@ protected:
// check which ones of these apply, probably all except GI and SDFGI
enum {
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
@@ -397,7 +403,6 @@ protected:
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 24,
};
struct GeometryInstanceLightmapSH {
@@ -563,38 +568,38 @@ public:
void _geometry_instance_update(GeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
- virtual GeometryInstance *geometry_instance_create(RID p_base);
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton);
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable);
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index);
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9);
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance);
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
-
- virtual uint32_t geometry_instance_get_pair_mask();
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count);
-
- virtual bool free(RID p_rid);
-
- virtual bool is_dynamic_gi_supported() const;
- virtual bool is_clustered_enabled() const;
- virtual bool is_volumetric_supported() const;
- virtual uint32_t get_max_elements() const;
+ virtual GeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
+ virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
+ virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
+ virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
+ virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
+ virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
+ virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
+ virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
+ virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
+ virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
+
+ virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
+ virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
+
+ virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+
+ virtual uint32_t geometry_instance_get_pair_mask() override;
+ virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
+ virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
+ virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
+ virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
+
+ virtual bool free(RID p_rid) override;
+
+ virtual bool is_dynamic_gi_supported() const override;
+ virtual bool is_clustered_enabled() const override;
+ virtual bool is_volumetric_supported() const override;
+ virtual uint32_t get_max_elements() const override;
RenderForwardMobile(RendererStorageRD *p_storage);
~RenderForwardMobile();
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 0d9dfbc51b..b5fb9fbc62 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
#include "render_forward_mobile.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
using namespace RendererSceneRenderImplementation;
@@ -291,12 +292,12 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
multisample_state.enable_alpha_to_one = true;
}
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
+ if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_blend;
if (depth_draw == DEPTH_DRAW_OPAQUE) {
depth_stencil.enable_depth_write = false; //alpha does not draw depth
}
- } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
+ } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
//none, blend state contains nothing
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
@@ -304,57 +305,16 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
pipelines[i][j][k].clear();
continue; // do not use this version (will error if using it is attempted)
}
-
- /*
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
- blend_state = blend_state_blend;
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
- depth_stencil.enable_depth_write = false; //alpha does not draw depth
- }
- } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) {
- if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
- //none, blend state contains nothing
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else {
- blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
- }
- } else {
- pipelines[i][j][k].clear();
- continue; // do not use this version (will error if using it is attempted)
- }
- */
} else {
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
+ if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
blend_state = blend_state_opaque;
- } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
+ } else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
//none, leave empty
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
} else {
// ???
}
-
- /*
- if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
- blend_state = blend_state_opaque;
- } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
- //none, leave empty
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal_roughness;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
- blend_state = blend_state_depth_normal_roughness_giprobe;
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_SDF) {
- blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
- } else {
- //specular write
- blend_state = blend_state_opaque_specular;
- depth_stencil.enable_depth_test = false;
- depth_stencil.enable_depth_write = false;
- }
- */
}
RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
@@ -585,10 +545,22 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
Vector<String> shader_versions;
shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // !BAS! SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_DEPTH_PASS_DP (maybe rename to SHADER_VERSION_SHADOW_PASS_DP?)
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_SHADOW_PASS_DP
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
+
+ // multiview versions of our shaders
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
+
shader.initialize(shader_versions, p_defines);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
+ shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
+ shader.set_variant_enabled(SHADER_VERSION_SHADOW_PASS_MULTIVIEW, false);
+ }
}
storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
@@ -603,7 +575,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix";
actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix";
actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
- actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix";
+ actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
actions.renames["MODELVIEW_MATRIX"] = "modelview";
actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
@@ -673,6 +645,10 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
+ actions.renames["VIEW_INDEX"] = "ViewIndex";
+ actions.renames["VIEW_MONO_LEFT"] = "0";
+ actions.renames["VIEW_RIGHT"] = "1";
+
//for light
actions.renames["VIEW"] = "view";
actions.renames["LIGHT_COLOR"] = "light_color";
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 1517197d25..f4f6ceeb1d 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -47,8 +47,13 @@ public:
SHADER_VERSION_COLOR_PASS,
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
SHADER_VERSION_SHADOW_PASS,
- SHADER_VERSION_DEPTH_PASS_DP,
+ SHADER_VERSION_SHADOW_PASS_DP,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
+
+ SHADER_VERSION_COLOR_PASS_MULTIVIEW,
+ SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
+ SHADER_VERSION_SHADOW_PASS_MULTIVIEW,
+
SHADER_VERSION_MAX
};
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index b2b919c40e..22888ddbe5 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -31,20 +31,21 @@
#include "pipeline_cache_rd.h"
#include "core/os/memory.h"
-RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe) {
+RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass) {
RD::PipelineMultisampleState multisample_state_version = multisample_state;
- multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id);
+ multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id, p_render_pass);
RD::PipelineRasterizationState raster_state_version = rasterization_state;
raster_state_version.wireframe = p_wireframe;
- RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags);
+ RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass);
ERR_FAIL_COND_V(pipeline.is_null(), RID());
versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
versions[version_count].framebuffer_id = p_framebuffer_format_id;
versions[version_count].vertex_id = p_vertex_format_id;
versions[version_count].wireframe = p_wireframe;
versions[version_count].pipeline = pipeline;
+ versions[version_count].render_pass = p_render_pass;
version_count++;
return pipeline;
}
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index b1c8f21ecc..387a8a038f 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -50,6 +50,7 @@ class PipelineCacheRD {
struct Version {
RD::VertexFormatID vertex_id;
RD::FramebufferFormatID framebuffer_id;
+ uint32_t render_pass;
bool wireframe;
RID pipeline;
};
@@ -57,7 +58,7 @@ class PipelineCacheRD {
Version *versions;
uint32_t version_count;
- RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe);
+ RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass);
void _clear();
@@ -65,7 +66,7 @@ public:
void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0);
void update_shader(RID p_shader);
- _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false) {
+ _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false, uint32_t p_render_pass = 0) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
"Attempted to use an unused shader variant (shader is null),");
@@ -74,13 +75,13 @@ public:
spin_lock.lock();
RID result;
for (uint32_t i = 0; i < version_count; i++) {
- if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe) {
+ if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe && versions[i].render_pass == p_render_pass) {
result = versions[i].pipeline;
spin_lock.unlock();
return result;
}
}
- result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe);
+ result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe, p_render_pass);
spin_lock.unlock();
return result;
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 9d325fe69b..026969c09f 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -408,6 +408,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
PushConstant push_constant;
Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform;
+ Transform2D draw_transform;
_update_transform_2d_to_mat2x3(base_transform, push_constant.world);
Color base_color = p_item->final_modulate;
@@ -464,8 +465,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RID last_texture;
Size2 texpixel_size;
+ bool skipping = false;
+
const Item::Command *c = p_item->commands;
while (c) {
+ if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) {
+ c = c->next;
+ continue;
+ }
+
push_constant.flags = base_flags | (push_constant.flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config
switch (c->type) {
@@ -724,7 +732,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
mesh_instance = m->mesh_instance;
texture = m->texture;
modulate = m->modulate;
- _update_transform_2d_to_mat2x3(base_transform * m->transform, push_constant.world);
+ _update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, push_constant.world);
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
RID multimesh = mm->multimesh;
@@ -857,10 +865,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
for (int j = 0; j < 6; j++) {
push_constant.world[j] = world_backup[j];
}
-
} break;
case Item::Command::TYPE_TRANSFORM: {
const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c);
+ draw_transform = transform->xform;
_update_transform_2d_to_mat2x3(base_transform * transform->xform, push_constant.world);
} break;
@@ -879,6 +887,14 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
} break;
+ case Item::Command::TYPE_ANIMATION_SLICE: {
+ const Item::CommandAnimationSlice *as = static_cast<const Item::CommandAnimationSlice *>(c);
+ double current_time = RendererCompositorRD::singleton->get_total_time();
+ double local_time = Math::fposmod(current_time - as->offset, as->animation_length);
+ skipping = !(local_time >= as->slice_begin && local_time < as->slice_end);
+
+ RenderingServerDefault::redraw_request(); // animation visible means redraw request
+ } break;
}
c = c->next;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 8c1376e2dc..1bc3769450 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -457,8 +457,6 @@ public:
void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {}
- void draw_window_margins(int *p_margins, RID *p_margin_textures) {}
-
virtual void set_shadow_texture_size(int p_size);
void set_time(double p_time);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 1337d36762..f9ac7c8fa3 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -31,7 +31,7 @@
#include "renderer_compositor_rd.h"
#include "core/config/project_settings.h"
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
void RendererCompositorRD::prepare_for_blitting_render_targets() {
RD::get_singleton()->prepare_screen_for_drawing();
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index 43a4058ab6..9228e06d7e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -1862,7 +1862,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
#if 0
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(cascades[cascade].sdf, 0);
Ref<Image> img;
- img.instance();
+ img.instantiate();
for (uint32_t i = 0; i < cascade_size; i++) {
Vector<uint8_t> subarr = data.subarray(128 * 128 * i, 128 * 128 * (i + 1) - 1);
img->create(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr);
@@ -1875,7 +1875,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
#if 0
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(render_albedo, 0);
Ref<Image> img;
- img.instance();
+ img.instantiate();
for (uint32_t i = 0; i < cascade_size; i++) {
Vector<uint8_t> subarr = data.subarray(128 * 128 * i * 2, 128 * 128 * (i + 1) * 2 - 1);
img->createcascade_size, cascade_size, false, Image::FORMAT_RGB565, subarr);
@@ -3078,9 +3078,6 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
gipd.bias = storage->voxel_gi_get_bias(base_probe);
gipd.normal_bias = storage->voxel_gi_get_normal_bias(base_probe);
gipd.blend_ambient = !storage->voxel_gi_is_interior(base_probe);
- gipd.anisotropy_strength = 0;
- gipd.ao = storage->voxel_gi_get_ao(base_probe);
- gipd.ao_size = Math::pow(storage->voxel_gi_get_ao_size(base_probe), 4.0f);
gipd.mipmaps = gipi->mipmaps.size();
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index 45fc7b3951..128bf09063 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -611,9 +611,9 @@ public:
uint32_t blend_ambient;
uint32_t texture_slot;
- float anisotropy_strength;
- float ao;
- float ao_size;
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t pad2;
uint32_t mipmaps;
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index ff7e6c502f..089651cbfb 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -486,7 +486,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
color.b *= env->bg_energy;
Ref<Image> ret;
- ret.instance();
+ ret.instantiate();
ret->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF);
for (int i = 0; i < p_size.width; i++) {
for (int j = 0; j < p_size.height; j++) {
@@ -1728,7 +1728,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.half_screen_size = Size2i(buffer_width, buffer_height);
settings.quarter_screen_size = Size2i(half_width, half_height);
- storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid);
+ storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ssao.downsample_uniform_set, rb->ssao.gather_uniform_set, rb->ssao.importance_map_uniform_set);
}
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
@@ -1857,6 +1857,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
}
+ tonemap.view_count = p_render_data->view_count;
+
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
}
@@ -2112,7 +2114,9 @@ float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID
return rb->volumetric_fog->spread;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) {
+void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
+ ERR_FAIL_COND_MSG(p_view_count == 0, "Must have atleast 1 view");
+
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
rb->width = p_width;
rb->height = p_height;
@@ -2120,6 +2124,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->msaa = p_msaa;
rb->screen_space_aa = p_screen_space_aa;
rb->use_debanding = p_use_debanding;
+ rb->view_count = p_view_count;
if (is_clustered_enabled()) {
if (rb->cluster_builder == nullptr) {
@@ -2132,9 +2137,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
{
RD::TextureFormat tf;
+ if (rb->view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ }
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = rb->width;
tf.height = rb->height;
+ tf.array_layers = rb->view_count; // create a layer for every view
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -2147,6 +2156,9 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
{
RD::TextureFormat tf;
+ if (rb->view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ }
if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) {
tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
} else {
@@ -2156,6 +2168,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.width = p_width;
tf.height = p_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+ tf.array_layers = rb->view_count; // create a layer for every view
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
@@ -2166,7 +2179,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
- rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa);
+ rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
@@ -3498,11 +3511,9 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
if (p_render_data->render_buffers.is_valid() && p_use_gi) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers);
ERR_FAIL_COND(rb == nullptr);
- if (rb->sdfgi == nullptr) {
- return;
+ if (rb->sdfgi != nullptr) {
+ rb->sdfgi->store_probes();
}
-
- rb->sdfgi->store_probes();
}
render_state.cube_shadows.clear();
@@ -3630,7 +3641,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data) {
// getting this here now so we can direct call a bunch of things more easily
RenderBuffers *rb = nullptr;
if (p_render_buffers.is_valid()) {
@@ -3643,11 +3654,19 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D
{
render_data.render_buffers = p_render_buffers;
- render_data.cam_transform = p_cam_transform;
- render_data.cam_projection = p_cam_projection;
- render_data.cam_ortogonal = p_cam_projection.is_orthogonal(); // !BAS! Shouldn't this be p_cam_ortogonal ?
- render_data.z_near = p_cam_projection.get_z_near();
- render_data.z_far = p_cam_projection.get_z_far();
+ // Our first camera is used by default
+ render_data.cam_transform = p_camera_data->main_transform;
+ render_data.cam_projection = p_camera_data->main_projection;
+ render_data.view_projection[0] = p_camera_data->main_projection;
+ render_data.cam_ortogonal = p_camera_data->is_ortogonal;
+
+ render_data.view_count = p_camera_data->view_count;
+ for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
+ render_data.view_projection[v] = p_camera_data->view_projection[v];
+ }
+
+ render_data.z_near = p_camera_data->main_projection.get_z_near();
+ render_data.z_far = p_camera_data->main_projection.get_z_far();
render_data.instances = &p_instances;
render_data.lights = &p_lights;
@@ -3662,8 +3681,9 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D
render_data.reflection_probe = p_reflection_probe;
render_data.reflection_probe_pass = p_reflection_probe_pass;
- render_data.lod_distance_multiplier = p_cam_projection.get_lod_multiplier();
- render_data.lod_camera_plane = Plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
+ // this should be the same for all cameras..
+ render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
+ render_data.lod_camera_plane = Plane(p_camera_data->main_transform.get_origin(), -p_camera_data->main_transform.basis.get_axis(Vector3::AXIS_Z));
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
render_data.screen_lod_threshold = 0.0;
@@ -3730,17 +3750,18 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D
current_cluster_builder = nullptr;
}
- if (rb != nullptr && rb->sdfgi != nullptr) {
- rb->sdfgi->update_cascades();
-
- rb->sdfgi->pre_process_gi(p_cam_transform, &render_data, this);
- }
-
render_state.voxel_gi_count = 0;
- if (rb != nullptr && rb->sdfgi != nullptr) {
- gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
- rb->sdfgi->update_light();
+ if (rb != nullptr) {
+ if (rb->sdfgi) {
+ rb->sdfgi->update_cascades();
+ rb->sdfgi->pre_process_gi(render_data.cam_transform, &render_data, this);
+ rb->sdfgi->update_light();
+ }
+
+ if (p_voxel_gi_instances.size()) {
+ gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
+ }
}
render_state.depth_prepass_used = false;
@@ -3782,7 +3803,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform3D
_render_buffers_post_process_and_tonemap(&render_data);
_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) {
- rb->sdfgi->debug_draw(p_cam_projection, p_cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
+ rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
}
}
}
@@ -4153,7 +4174,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
{
PackedByteArray data = RD::get_singleton()->texture_get_data(albedo_alpha_tex, 0);
Ref<Image> img;
- img.instance();
+ img.instantiate();
img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
RD::get_singleton()->free(albedo_alpha_tex);
ret.push_back(img);
@@ -4162,7 +4183,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
{
PackedByteArray data = RD::get_singleton()->texture_get_data(normal_tex, 0);
Ref<Image> img;
- img.instance();
+ img.instantiate();
img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
RD::get_singleton()->free(normal_tex);
ret.push_back(img);
@@ -4171,7 +4192,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
{
PackedByteArray data = RD::get_singleton()->texture_get_data(orm_tex, 0);
Ref<Image> img;
- img.instance();
+ img.instantiate();
img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
RD::get_singleton()->free(orm_tex);
ret.push_back(img);
@@ -4180,7 +4201,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
{
PackedByteArray data = RD::get_singleton()->texture_get_data(emission_tex, 0);
Ref<Image> img;
- img.instance();
+ img.instantiate();
img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBAH, data);
RD::get_singleton()->free(emission_tex);
ret.push_back(img);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index c8fcbecc95..d9df467d48 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -50,6 +50,10 @@ struct RenderDataRD {
CameraMatrix cam_projection = CameraMatrix();
bool cam_ortogonal = false;
+ // For stereo rendering
+ uint32_t view_count = 1;
+ CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+
float z_near = 0.0;
float z_far = 0.0;
@@ -87,7 +91,7 @@ protected:
double time_step = 0;
struct RenderBufferData {
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) = 0;
+ virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0;
virtual ~RenderBufferData() {}
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
@@ -411,6 +415,7 @@ private:
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_debanding = false;
+ uint32_t view_count = 1;
RID render_target;
@@ -454,6 +459,10 @@ private:
Vector<RID> ao_pong_slices;
RID ao_final;
RID importance_map[2];
+
+ RID downsample_uniform_set;
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
} ssao;
struct SSR {
@@ -745,10 +754,10 @@ public:
/* SHADOW ATLAS API */
- RID shadow_atlas_create();
- void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false);
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
+ virtual RID shadow_atlas_create() override;
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) override;
+ virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
+ virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override;
_FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND_V(!atlas, false);
@@ -767,9 +776,9 @@ public:
return Size2(atlas->size, atlas->size);
}
- void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false);
- int get_directional_light_shadow_size(RID p_light_intance);
- void set_directional_shadow_count(int p_count);
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) override;
+ virtual int get_directional_light_shadow_size(RID p_light_intance) override;
+ virtual void set_directional_shadow_count(int p_count) override;
_FORCE_INLINE_ RID directional_shadow_get_texture() {
return directional_shadow.depth;
@@ -781,43 +790,43 @@ public:
/* SDFGI UPDATE */
- virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position);
- virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const;
- virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const;
- virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const;
+ virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
+ virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const override;
+ virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override;
+ virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override;
RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
/* SKY API */
- virtual RID sky_allocate();
- virtual void sky_initialize(RID p_rid);
+ virtual RID sky_allocate() override;
+ virtual void sky_initialize(RID p_rid) override;
- void sky_set_radiance_size(RID p_sky, int p_radiance_size);
- void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
- void sky_set_material(RID p_sky, RID p_material);
- Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size);
+ virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) override;
+ virtual void sky_set_mode(RID p_sky, RS::SkyMode p_mode) override;
+ virtual void sky_set_material(RID p_sky, RID p_material) override;
+ virtual Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) override;
/* ENVIRONMENT API */
- virtual RID environment_allocate();
- virtual void environment_initialize(RID p_rid);
+ virtual RID environment_allocate() override;
+ virtual void environment_initialize(RID p_rid) override;
- void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
- void environment_set_sky(RID p_env, RID p_sky);
- void environment_set_sky_custom_fov(RID p_env, float p_scale);
- void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
- void environment_set_bg_color(RID p_env, const Color &p_color);
- void environment_set_bg_energy(RID p_env, float p_energy);
- void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
- void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color());
+ virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override;
+ virtual void environment_set_sky(RID p_env, RID p_sky) override;
+ virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) override;
+ virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override;
+ virtual void environment_set_bg_color(RID p_env, const Color &p_color) override;
+ virtual void environment_set_bg_energy(RID p_env, float p_energy) override;
+ virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override;
+ virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) override;
- RS::EnvironmentBG environment_get_background(RID p_env) const;
+ virtual RS::EnvironmentBG environment_get_background(RID p_env) const override;
RID environment_get_sky(RID p_env) const;
float environment_get_sky_custom_fov(RID p_env) const;
Basis environment_get_sky_orientation(RID p_env) const;
Color environment_get_bg_color(RID p_env) const;
float environment_get_bg_energy(RID p_env) const;
- int environment_get_canvas_max_layer(RID p_env) const;
+ virtual int environment_get_canvas_max_layer(RID p_env) const override;
Color environment_get_ambient_light_color(RID p_env) const;
RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
float environment_get_ambient_light_energy(RID p_env) const;
@@ -825,13 +834,13 @@ public:
RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
Color environment_get_ao_color(RID p_env) const;
- bool is_environment(RID p_env) const;
+ virtual bool is_environment(RID p_env) const override;
- void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap);
- void environment_glow_set_use_bicubic_upscale(bool p_enable);
- void environment_glow_set_use_high_quality(bool p_enable);
+ virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) override;
+ virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override;
+ virtual void environment_glow_set_use_high_quality(bool p_enable) override;
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective);
+ virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override;
bool environment_is_fog_enabled(RID p_env) const;
Color environment_get_fog_light_color(RID p_env) const;
float environment_get_fog_light_energy(RID p_env) const;
@@ -841,47 +850,47 @@ public:
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount);
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount) override;
- virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth);
- virtual void environment_set_volumetric_fog_filter_active(bool p_enable);
+ virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override;
+ virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override;
- void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
- void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
- void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to);
+ virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override;
+ virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override;
+ virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
bool environment_is_ssao_enabled(RID p_env) const;
float environment_get_ssao_ao_affect(RID p_env) const;
float environment_get_ssao_light_affect(RID p_env) const;
bool environment_is_ssr_enabled(RID p_env) const;
bool environment_is_sdfgi_enabled(RID p_env) const;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
- virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count);
- virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames);
- virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update);
+ virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override;
+ virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override;
+ virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override;
+ virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override;
- void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality);
+ virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override;
RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const;
- void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
- void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction);
+ virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override;
+ virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override;
- virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size);
+ virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
- virtual RID camera_effects_allocate();
- virtual void camera_effects_initialize(RID p_rid);
+ virtual RID camera_effects_allocate() override;
+ virtual void camera_effects_initialize(RID p_rid) override;
- virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter);
- virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape);
+ virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override;
+ virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override;
- virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount);
- virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure);
+ virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override;
+ virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
- RID light_instance_create(RID p_light);
- void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform);
- void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb);
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2());
- void light_instance_mark_visible(RID p_light_instance);
+ virtual RID light_instance_create(RID p_light) override;
+ virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
+ virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
+ virtual void light_instance_mark_visible(RID p_light_instance) override;
_FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
LightInstance *li = light_instance_owner.getornull(p_light_instance);
@@ -1008,9 +1017,9 @@ public:
return li->light_type;
}
- virtual RID reflection_atlas_create();
- virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count);
- virtual int reflection_atlas_get_size(RID p_ref_atlas) const;
+ virtual RID reflection_atlas_create() override;
+ virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override;
+ virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
_FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) {
ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas);
@@ -1018,13 +1027,13 @@ public:
return atlas->reflection;
}
- virtual RID reflection_probe_instance_create(RID p_probe);
- virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform);
- virtual void reflection_probe_release_atlas_index(RID p_instance);
- virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
- virtual bool reflection_probe_instance_has_reflection(RID p_instance);
- virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas);
- virtual bool reflection_probe_instance_postprocess_step(RID p_instance);
+ virtual RID reflection_probe_instance_create(RID p_probe) override;
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
+ virtual void reflection_probe_release_atlas_index(RID p_instance) override;
+ virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
+ virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index);
@@ -1077,8 +1086,8 @@ public:
return rpi->atlas_index;
}
- virtual RID decal_instance_create(RID p_decal);
- virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform);
+ virtual RID decal_instance_create(RID p_decal) override;
+ virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override;
_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal) const {
DecalInstance *decal = decal_instance_owner.getornull(p_decal);
@@ -1090,8 +1099,8 @@ public:
return decal->transform;
}
- virtual RID lightmap_instance_create(RID p_lightmap);
- virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform);
+ virtual RID lightmap_instance_create(RID p_lightmap) override;
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
_FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr;
}
@@ -1109,17 +1118,17 @@ public:
/* gi light probes */
- RID voxel_gi_instance_create(RID p_base);
- void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
- bool voxel_gi_needs_update(RID p_probe) const;
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);
- void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) { gi.voxel_gi_quality = p_quality; }
+ virtual RID voxel_gi_instance_create(RID p_base) override;
+ virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override;
+ virtual bool voxel_gi_needs_update(RID p_probe) const override;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override;
+ virtual void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) override { gi.voxel_gi_quality = p_quality; }
/* render buffers */
- RID render_buffers_create();
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding);
- void gi_set_use_half_resolution(bool p_enable);
+ virtual RID render_buffers_create() override;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void gi_set_use_half_resolution(bool p_enable) override;
RID render_buffers_get_ao_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
@@ -1147,30 +1156,30 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr);
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) override;
- void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances);
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override;
- virtual void set_scene_pass(uint64_t p_pass) {
+ virtual void set_scene_pass(uint64_t p_pass) override {
scene_pass = p_pass;
}
_FORCE_INLINE_ uint64_t get_scene_pass() {
return scene_pass;
}
- virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit);
- virtual bool screen_space_roughness_limiter_is_active() const;
+ virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) override;
+ virtual bool screen_space_roughness_limiter_is_active() const override;
virtual float screen_space_roughness_limiter_get_amount() const;
virtual float screen_space_roughness_limiter_get_limit() const;
- virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality);
+ virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override;
RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
- virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale);
+ virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override;
- virtual void shadows_quality_set(RS::ShadowQuality p_quality);
- virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality);
+ virtual void shadows_quality_set(RS::ShadowQuality p_quality) override;
+ virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) override;
_FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const { return shadows_quality; }
_FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const { return directional_shadow_quality; }
_FORCE_INLINE_ float shadows_quality_radius_get() const { return shadows_quality_radius; }
@@ -1189,18 +1198,18 @@ public:
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
- virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size);
+ virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override;
- virtual bool free(RID p_rid);
+ virtual bool free(RID p_rid) override;
- virtual void update();
+ virtual void update() override;
- virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw);
+ virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override;
_FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const {
return debug_draw;
}
- void set_time(double p_time, double p_step);
+ virtual void set_time(double p_time, double p_step) override;
RID get_reflection_probe_buffer();
RID get_omni_light_buffer();
@@ -1209,7 +1218,7 @@ public:
RID get_decal_buffer();
int get_max_directional_lights() const;
- void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
+ virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override;
virtual bool is_dynamic_gi_supported() const;
virtual bool is_clustered_enabled() const;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index e68f466015..956609b77e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
#include "renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/rendering_server_default.h"
////////////////////////////////////////////////////////////////////////////////
@@ -126,8 +127,12 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
depth_stencil_state.enable_depth_test = true;
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
- RID shader_variant = scene_singleton->sky.sky_shader.shader.version_get_shader(version, i);
- pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
+ if (scene_singleton->sky.sky_shader.shader.is_variant_enabled(i)) {
+ RID shader_variant = scene_singleton->sky.sky_shader.shader.version_get_shader(version, i);
+ pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ pipelines[i].clear();
+ }
}
valid = true;
@@ -318,6 +323,63 @@ RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
}
////////////////////////////////////////////////////////////////////////////////
+// Render sky
+
+static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) {
+ p_array[0] = p_basis.elements[0][0];
+ p_array[1] = p_basis.elements[1][0];
+ p_array[2] = p_basis.elements[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_basis.elements[0][1];
+ p_array[5] = p_basis.elements[1][1];
+ p_array[6] = p_basis.elements[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_basis.elements[0][2];
+ p_array[9] = p_basis.elements[1][2];
+ p_array[10] = p_basis.elements[2][2];
+ p_array[11] = 0;
+}
+
+void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) {
+ SkyPushConstant sky_push_constant;
+
+ memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ // We only need key components of our projection matrix
+ sky_push_constant.projections[v][0] = p_projections[v].matrix[2][0];
+ sky_push_constant.projections[v][1] = p_projections[v].matrix[0][0];
+ sky_push_constant.projections[v][2] = p_projections[v].matrix[2][1];
+ sky_push_constant.projections[v][3] = p_projections[v].matrix[1][1];
+ }
+ sky_push_constant.position[0] = p_position.x;
+ sky_push_constant.position[1] = p_position.y;
+ sky_push_constant.position[2] = p_position.z;
+ sky_push_constant.multiplier = p_multiplier;
+ sky_push_constant.time = p_time;
+ store_transform_3x3(p_orientation, sky_push_constant.orientation);
+
+ RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
+
+ RD::DrawListID draw_list = p_list;
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format));
+
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, 0);
+ if (p_uniform_set.is_valid()) { //material may not have uniform set
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1);
+ }
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3);
+
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+}
+
+////////////////////////////////////////////////////////////////////////////////
// ReflectionData
void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
@@ -623,7 +685,7 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(RendererStorageRD *p_storage,
RD::get_singleton()->free(rad_tex);
Ref<Image> img;
- img.instance();
+ img.instantiate();
img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data);
for (int i = 0; i < p_size.width; i++) {
for (int j = 0; j < p_size.height; j++) {
@@ -694,7 +756,18 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n"); // Cubemap
sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_HALF_RES_PASS\n"); // Half Res Cubemap
sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_QUARTER_RES_PASS\n"); // Quarter res Cubemap
+
+ sky_modes.push_back("\n#define USE_MULTIVIEW\n"); // Full size multiview
+ sky_modes.push_back("\n#define USE_HALF_RES_PASS\n#define USE_MULTIVIEW\n"); // Half Res multiview
+ sky_modes.push_back("\n#define USE_QUARTER_RES_PASS\n#define USE_MULTIVIEW\n"); // Quarter res multiview
+
sky_shader.shader.initialize(sky_modes, defines);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ sky_shader.shader.set_variant_enabled(SKY_VERSION_BACKGROUND_MULTIVIEW, false);
+ sky_shader.shader.set_variant_enabled(SKY_VERSION_HALF_RES_MULTIVIEW, false);
+ sky_shader.shader.set_variant_enabled(SKY_VERSION_QUARTER_RES_MULTIVIEW, false);
+ }
}
// register our shader funds
@@ -876,6 +949,41 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
sky_scene_state.fog_only_texture_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES);
}
+
+ { //create index array for copy shaders
+ Vector<uint8_t> pv;
+ pv.resize(6 * 4);
+ {
+ uint8_t *w = pv.ptrw();
+ int *p32 = (int *)w;
+ p32[0] = 0;
+ p32[1] = 1;
+ p32[2] = 2;
+ p32[3] = 0;
+ p32[4] = 2;
+ p32[5] = 3;
+ }
+ index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
+ index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6);
+ }
+}
+
+RendererSceneSkyRD::~RendererSceneSkyRD() {
+ // TODO cleanup anything created in init...
+
+ if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.uniform_set);
+ }
+
+ if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.default_fog_uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.default_fog_uniform_set);
+ }
+
+ if (RD::get_singleton()->uniform_set_is_valid(sky_scene_state.fog_only_texture_uniform_set)) {
+ RD::get_singleton()->free(sky_scene_state.fog_only_texture_uniform_set);
+ }
+
+ RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
@@ -1140,7 +1248,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
}
@@ -1158,7 +1266,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
}
@@ -1172,7 +1280,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- storage->get_effects()->render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
@@ -1213,9 +1321,12 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
}
}
-void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time) {
+void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_view_count == 0);
+ ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
+
Sky *sky = get_sky(p_env->sky);
ERR_FAIL_COND(!sky);
@@ -1257,24 +1368,28 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
float multiplier = p_env->bg_energy;
float custom_fov = p_env->sky_custom_fov;
+
// Camera
CameraMatrix camera;
+ uint32_t view_count = p_view_count;
+ const CameraMatrix *projections = p_projections;
if (custom_fov) {
- float near_plane = p_projection.get_z_near();
- float far_plane = p_projection.get_z_far();
- float aspect = p_projection.get_aspect();
+ // With custom fov we don't support stereo...
+ float near_plane = p_projections[0].get_z_near();
+ float far_plane = p_projections[0].get_z_far();
+ float aspect = p_projections[0].get_aspect();
camera.set_perspective(custom_fov, aspect, near_plane, far_plane);
- } else {
- camera = p_projection;
+ view_count = 1;
+ projections = &camera;
}
sky_transform = p_transform.basis * sky_transform;
if (shader_data->uses_quarter_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
@@ -1282,12 +1397,12 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- storage->get_effects()->render_sky(draw_list, p_time, sky->quarter_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
if (shader_data->uses_half_res) {
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
@@ -1295,11 +1410,11 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- storage->get_effects()->render_sky(draw_list, p_time, sky->half_res_framebuffer, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
- PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND];
+ PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND];
RID texture_uniform_set;
if (sky) {
@@ -1309,7 +1424,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- storage->get_effects()->render_sky(draw_list, p_time, p_fb, sky_scene_state.uniform_set, sky_scene_state.fog_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin);
+ _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 063e4e662e..1292622fca 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -43,9 +43,6 @@
class RendererSceneRenderRD;
class RendererSceneSkyRD {
-private:
- RendererStorageRD *storage;
-
public:
enum SkySet {
SKY_SET_UNIFORMS,
@@ -55,6 +52,22 @@ public:
SKY_SET_MAX
};
+ // Skys need less info from Directional Lights than the normal shaders
+ struct SkyDirectionalLightData {
+ float direction[3];
+ float energy;
+ float color[3];
+ float size;
+ uint32_t enabled;
+ uint32_t pad[3];
+ };
+
+private:
+ RendererStorageRD *storage;
+
+ RID index_buffer;
+ RID index_array;
+
enum SkyTextureSetVersion {
SKY_TEXTURE_SET_BACKGROUND,
SKY_TEXTURE_SET_HALF_RES,
@@ -72,19 +85,61 @@ public:
SKY_VERSION_CUBEMAP,
SKY_VERSION_CUBEMAP_HALF_RES,
SKY_VERSION_CUBEMAP_QUARTER_RES,
+
+ SKY_VERSION_BACKGROUND_MULTIVIEW,
+ SKY_VERSION_HALF_RES_MULTIVIEW,
+ SKY_VERSION_QUARTER_RES_MULTIVIEW,
+
SKY_VERSION_MAX
};
- // Skys need less info from Directional Lights than the normal shaders
- struct SkyDirectionalLightData {
- float direction[3];
- float energy;
- float color[3];
- float size;
- uint32_t enabled;
- uint32_t pad[3];
+ struct SkyPushConstant {
+ float orientation[12]; // 48 - 48
+ float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 80
+ float position[3]; // 12 - 92
+ float multiplier; // 4 - 96
+ float time; // 4 - 100
+ float pad[3]; // 12 - 112 // Using pad to align on 16 bytes
+ // 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
+ };
+
+ struct SkyShaderData : public RendererStorageRD::ShaderData {
+ bool valid;
+ RID version;
+
+ PipelineCacheRD pipelines[SKY_VERSION_MAX];
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String path;
+ String code;
+ Map<StringName, RID> default_texture_params;
+
+ bool uses_time;
+ bool uses_position;
+ bool uses_half_res;
+ bool uses_quarter_res;
+ bool uses_light;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ SkyShaderData();
+ virtual ~SkyShaderData();
};
+ void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
+
+public:
struct SkySceneState {
struct UBO {
uint32_t volumetric_fog_enabled;
@@ -155,40 +210,6 @@ public:
void update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end);
};
- struct SkyShaderData : public RendererStorageRD::ShaderData {
- bool valid;
- RID version;
-
- PipelineCacheRD pipelines[SKY_VERSION_MAX];
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
-
- Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
-
- String path;
- String code;
- Map<StringName, RID> default_texture_params;
-
- bool uses_time;
- bool uses_position;
- bool uses_half_res;
- bool uses_quarter_res;
- bool uses_light;
-
- virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
- virtual bool is_animated() const;
- virtual bool casts_shadows() const;
- virtual Variant get_default_parameter(const StringName &p_parameter) const;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const;
- SkyShaderData();
- virtual ~SkyShaderData();
- };
-
/* Sky shader */
struct SkyShader {
@@ -265,12 +286,12 @@ public:
static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader);
RendererSceneSkyRD();
-
void init(RendererStorageRD *p_storage);
+ ~RendererSceneSkyRD();
void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time);
- void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time);
+ void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 05993829d1..3809c93e67 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -35,6 +35,7 @@
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_language.h"
bool RendererStorageRD::can_create_resources_async() const {
@@ -883,10 +884,6 @@ void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_im
RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data());
}
-void RendererStorageRD::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) {
- _texture_2d_update(p_texture, p_image, p_layer, true);
-}
-
void RendererStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
_texture_2d_update(p_texture, p_image, p_layer, false);
}
@@ -972,7 +969,7 @@ void RendererStorageRD::texture_2d_placeholder_initialize(RID p_texture) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image;
- image.instance();
+ image.instantiate();
image->create(4, 4, false, Image::FORMAT_RGBA8);
for (int i = 0; i < 4; i++) {
@@ -988,7 +985,7 @@ void RendererStorageRD::texture_2d_layered_placeholder_initialize(RID p_texture,
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image;
- image.instance();
+ image.instantiate();
image->create(4, 4, false, Image::FORMAT_RGBA8);
for (int i = 0; i < 4; i++) {
@@ -1014,7 +1011,7 @@ void RendererStorageRD::texture_3d_placeholder_initialize(RID p_texture) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image;
- image.instance();
+ image.instantiate();
image->create(4, 4, false, Image::FORMAT_RGBA8);
for (int i = 0; i < 4; i++) {
@@ -1044,7 +1041,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
Ref<Image> image;
- image.instance();
+ image.instantiate();
image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
if (tex->format != tex->validated_format) {
@@ -1067,7 +1064,7 @@ Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) c
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer);
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
Ref<Image> image;
- image.instance();
+ image.instantiate();
image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
if (tex->format != tex->validated_format) {
@@ -1095,7 +1092,7 @@ Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const {
Vector<uint8_t> sub_region = all_data.subarray(bs.offset, bs.offset + bs.buffer_size - 1);
Ref<Image> img;
- img.instance();
+ img.instantiate();
img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region);
ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>());
if (tex->format != tex->validated_format) {
@@ -1234,7 +1231,7 @@ RID RendererStorageRD::canvas_texture_allocate() {
return canvas_texture_owner.allocate_rid();
}
void RendererStorageRD::canvas_texture_initialize(RID p_rid) {
- canvas_texture_owner.initialize_rid(p_rid, memnew(CanvasTexture));
+ canvas_texture_owner.initialize_rid(p_rid);
}
void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
@@ -1440,8 +1437,10 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
material->shader_type = new_type;
}
- for (Map<StringName, RID>::Element *E = shader->default_texture_parameter.front(); E; E = E->next()) {
- shader->data->set_default_texture_param(E->key(), E->get());
+ if (shader->data) {
+ for (Map<StringName, RID>::Element *E = shader->default_texture_parameter.front(); E; E = E->next()) {
+ shader->data->set_default_texture_param(E->key(), E->get());
+ }
}
}
@@ -2461,7 +2460,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
} break;
case RS::ARRAY_COLOR: {
- attrib_stride += sizeof(int16_t) * 4;
+ attrib_stride += sizeof(uint32_t);
} break;
case RS::ARRAY_TEX_UV: {
attrib_stride += sizeof(float) * 2;
@@ -2653,7 +2652,7 @@ RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) cons
return mesh->blend_shape_mode;
}
-void RendererStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
@@ -2664,6 +2663,30 @@ void RendererStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, in
RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r);
}
+void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r);
+}
+
+void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r);
+}
+
void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
@@ -2932,7 +2955,8 @@ RID RendererStorageRD::mesh_instance_create(RID p_base) {
Mesh *mesh = mesh_owner.getornull(p_base);
ERR_FAIL_COND_V(!mesh, RID());
- MeshInstance *mi = memnew(MeshInstance);
+ RID rid = mesh_instance_owner.make_rid();
+ MeshInstance *mi = mesh_instance_owner.getornull(rid);
mi->mesh = mesh;
@@ -2944,7 +2968,7 @@ RID RendererStorageRD::mesh_instance_create(RID p_base) {
mi->dirty = true;
- return mesh_instance_owner.make_rid(mi);
+ return rid;
}
void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance);
@@ -3231,8 +3255,8 @@ void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surf
case RS::ARRAY_COLOR: {
vd.offset = attribute_stride;
- vd.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- attribute_stride += sizeof(int16_t) * 4;
+ vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ attribute_stride += sizeof(int8_t) * 4;
buffer = s->attribute_buffer;
} break;
case RS::ARRAY_TEX_UV: {
@@ -3823,7 +3847,7 @@ void RendererStorageRD::_update_dirty_multimeshes() {
if (multimesh->data_cache_used_dirty_regions) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- uint32_t visible_region_count = (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
@@ -3894,6 +3918,7 @@ void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting)
}
bool RendererStorageRD::particles_get_emitting(RID p_particles) {
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND_V(!particles, false);
@@ -4216,6 +4241,10 @@ void RendererStorageRD::particles_request_process(RID p_particles) {
}
AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
+ if (RSG::threaded) {
+ WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
+ }
+
const Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND_V(!particles, AABB());
@@ -5100,6 +5129,7 @@ void RendererStorageRD::update_particles() {
}
bool RendererStorageRD::particles_is_inactive(RID p_particles) const {
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
const Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND_V(!particles, false);
return !particles->emitting && particles->inactive;
@@ -5533,6 +5563,59 @@ void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_
pci->active = p_active;
}
+/* VISIBILITY NOTIFIER */
+
+RID RendererStorageRD::visibility_notifier_allocate() {
+ return visibility_notifier_owner.allocate_rid();
+}
+void RendererStorageRD::visibility_notifier_initialize(RID p_notifier) {
+ visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
+}
+void RendererStorageRD::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ ERR_FAIL_COND(!vn);
+ vn->aabb = p_aabb;
+ vn->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
+}
+void RendererStorageRD::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ ERR_FAIL_COND(!vn);
+ vn->enter_callback = p_enter_callbable;
+ vn->exit_callback = p_exit_callable;
+}
+
+AABB RendererStorageRD::visibility_notifier_get_aabb(RID p_notifier) const {
+ const VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ ERR_FAIL_COND_V(!vn, AABB());
+ return vn->aabb;
+}
+void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
+ ERR_FAIL_COND(!vn);
+
+ if (p_enter) {
+ if (!vn->enter_callback.is_null()) {
+ if (p_deferred) {
+ vn->enter_callback.call_deferred(nullptr, 0);
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->enter_callback.call(nullptr, 0, r, ce);
+ }
+ }
+ } else {
+ if (!vn->exit_callback.is_null()) {
+ if (p_deferred) {
+ vn->exit_callback.call_deferred(nullptr, 0);
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->exit_callback.call(nullptr, 0, r, ce);
+ }
+ }
+ }
+}
+
/* SKELETON API */
RID RendererStorageRD::skeleton_allocate() {
@@ -5948,20 +6031,6 @@ RS::LightDirectionalShadowMode RendererStorageRD::light_directional_get_shadow_m
return light->directional_shadow_mode;
}
-void RendererStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) {
- Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_range_mode = p_range_mode;
-}
-
-RS::LightDirectionalShadowDepthRangeMode RendererStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const {
- const Light *light = light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
-
- return light->directional_range_mode;
-}
-
uint32_t RendererStorageRD::light_get_max_sdfgi_cascade(RID p_light) {
const Light *light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light, 0);
@@ -6555,32 +6624,6 @@ float RendererStorageRD::voxel_gi_get_energy(RID p_voxel_gi) const {
return voxel_gi->energy;
}
-void RendererStorageRD::voxel_gi_set_ao(RID p_voxel_gi, float p_ao) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->ao = p_ao;
-}
-
-float RendererStorageRD::voxel_gi_get_ao(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->ao;
-}
-
-void RendererStorageRD::voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->ao_size = p_strength;
-}
-
-float RendererStorageRD::voxel_gi_get_ao_size(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->ao_size;
-}
-
void RendererStorageRD::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {
VoxelGI *voxel_gi = voxel_gi_owner.getornull(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
@@ -6911,9 +6954,13 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) {
rd_format.width = rt->size.width;
rd_format.height = rt->size.height;
rd_format.depth = 1;
- rd_format.array_layers = 1;
+ rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
rd_format.mipmaps = 1;
- rd_format.texture_type = RD::TEXTURE_TYPE_2D;
+ if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
+ rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else {
+ rd_format.texture_type = RD::TEXTURE_TYPE_2D;
+ }
rd_format.samples = RD::TEXTURE_SAMPLES_1;
rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
rd_format.shareable_formats.push_back(rt->color_format);
@@ -6925,7 +6972,7 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) {
Vector<RID> fb_textures;
fb_textures.push_back(rt->color);
- rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures);
+ rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
if (rt->framebuffer.is_null()) {
_clear_render_target(rt);
ERR_FAIL_COND(rt->framebuffer.is_null());
@@ -7039,12 +7086,15 @@ void RendererStorageRD::render_target_set_position(RID p_render_target, int p_x,
//unused for this render target
}
-void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height) {
+void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
- rt->size.x = p_width;
- rt->size.y = p_height;
- _update_render_target(rt);
+ if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) {
+ rt->size.x = p_width;
+ rt->size.y = p_height;
+ rt->view_count = p_view_count;
+ _update_render_target(rt);
+ }
}
RID RendererStorageRD::render_target_get_texture(RID p_render_target) {
@@ -7581,6 +7631,9 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
} else if (particles_collision_owner.owns(p_base)) {
ParticlesCollision *pc = particles_collision_owner.getornull(p_base);
p_instance->update_dependency(&pc->dependency);
+ } else if (visibility_notifier_owner.owns(p_base)) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_base);
+ p_instance->update_dependency(&vn->dependency);
}
}
@@ -7619,6 +7672,9 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
if (particles_collision_owner.owns(p_rid)) {
return RS::INSTANCE_PARTICLES_COLLISION;
}
+ if (visibility_notifier_owner.owns(p_rid)) {
+ return RS::INSTANCE_VISIBLITY_NOTIFIER;
+ }
return RS::INSTANCE_NONE;
}
@@ -8552,6 +8608,7 @@ bool RendererStorageRD::free(RID p_rid) {
if (texture_owner.owns(p_rid)) {
Texture *t = texture_owner.getornull(p_rid);
+ ERR_FAIL_COND_V(!t, false);
ERR_FAIL_COND_V(t->is_render_target, false);
if (RD::get_singleton()->texture_is_valid(t->rd_texture_srgb)) {
@@ -8588,8 +8645,6 @@ bool RendererStorageRD::free(RID p_rid) {
texture_owner.free(p_rid);
} else if (canvas_texture_owner.owns(p_rid)) {
- CanvasTexture *ct = canvas_texture_owner.getornull(p_rid);
- memdelete(ct);
canvas_texture_owner.free(p_rid);
} else if (shader_owner.owns(p_rid)) {
Shader *shader = shader_owner.getornull(p_rid);
@@ -8635,7 +8690,6 @@ bool RendererStorageRD::free(RID p_rid) {
mi->I = nullptr;
mesh_instance_owner.free(p_rid);
- memdelete(mi);
} else if (multimesh_owner.owns(p_rid)) {
_update_dirty_multimeshes();
@@ -8694,6 +8748,10 @@ bool RendererStorageRD::free(RID p_rid) {
}
particles_collision->dependency.deleted_notify(p_rid);
particles_collision_owner.free(p_rid);
+ } else if (visibility_notifier_owner.owns(p_rid)) {
+ VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_rid);
+ vn->dependency.deleted_notify(p_rid);
+ visibility_notifier_owner.free(p_rid);
} else if (particles_collision_instance_owner.owns(p_rid)) {
particles_collision_instance_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 8bfab545fd..26739b11da 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -221,7 +221,7 @@ private:
~CanvasTexture();
};
- RID_PtrOwner<CanvasTexture, true> canvas_texture_owner;
+ RID_Owner<CanvasTexture, true> canvas_texture_owner;
/* TEXTURE API */
struct Texture {
@@ -513,7 +513,7 @@ private:
void _mesh_instance_clear(MeshInstance *mi);
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
- mutable RID_PtrOwner<MeshInstance> mesh_instance_owner;
+ mutable RID_Owner<MeshInstance> mesh_instance_owner;
SelfList<MeshInstance>::List dirty_mesh_instance_weights;
SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
@@ -947,6 +947,17 @@ private:
mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+ /* visibility_notifier */
+
+ struct VisibilityNotifier {
+ AABB aabb;
+ Callable enter_callback;
+ Callable exit_callback;
+ Dependency dependency;
+ };
+
+ mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
+
/* Skeleton */
struct Skeleton {
@@ -991,7 +1002,6 @@ private:
uint32_t cull_mask = 0xFFFFFFFF;
RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
- RS::LightDirectionalShadowDepthRangeMode directional_range_mode = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
bool directional_blend_splits = false;
bool directional_sky_only = false;
uint64_t version = 0;
@@ -1065,8 +1075,6 @@ private:
float dynamic_range = 4.0;
float energy = 1.0;
- float ao = 0.0;
- float ao_size = 0.5;
float bias = 1.4;
float normal_bias = 0.0;
float propagation = 0.7;
@@ -1125,6 +1133,7 @@ private:
struct RenderTarget {
Size2i size;
+ uint32_t view_count;
RID framebuffer;
RID color;
@@ -1286,7 +1295,6 @@ public:
virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate);
- virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); //mostly used for video and streaming
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data);
virtual void texture_proxy_update(RID p_texture, RID p_proxy_to);
@@ -1445,7 +1453,9 @@ public:
virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode);
virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const;
- virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material);
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
@@ -1734,24 +1744,6 @@ public:
return multimesh->uniform_set_2d;
}
- /* IMMEDIATE API */
-
- RID immediate_allocate() { return RID(); }
- void immediate_initialize(RID p_immediate) {}
-
- virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {}
- virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {}
- virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) {}
- virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) {}
- virtual void immediate_color(RID p_immediate, const Color &p_color) {}
- virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {}
- virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {}
- virtual void immediate_end(RID p_immediate) {}
- virtual void immediate_clear(RID p_immediate) {}
- virtual void immediate_set_material(RID p_immediate, RID p_material) {}
- virtual RID immediate_get_material(RID p_immediate) const { return RID(); }
- virtual AABB immediate_get_aabb(RID p_immediate) const { return AABB(); }
-
/* SKELETON API */
RID skeleton_allocate();
@@ -1820,8 +1812,6 @@ public:
bool light_directional_get_blend_splits(RID p_light) const;
void light_directional_set_sky_only(RID p_light, bool p_sky_only);
bool light_directional_is_sky_only(RID p_light) const;
- void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode);
- RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
@@ -2044,12 +2034,6 @@ public:
void voxel_gi_set_energy(RID p_voxel_gi, float p_energy);
float voxel_gi_get_energy(RID p_voxel_gi) const;
- void voxel_gi_set_ao(RID p_voxel_gi, float p_ao);
- float voxel_gi_get_ao(RID p_voxel_gi) const;
-
- void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength);
- float voxel_gi_get_ao_size(RID p_voxel_gi) const;
-
void voxel_gi_set_bias(RID p_voxel_gi, float p_bias);
float voxel_gi_get_bias(RID p_voxel_gi) const;
@@ -2252,6 +2236,14 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
+ virtual RID visibility_notifier_allocate();
+ virtual void visibility_notifier_initialize(RID p_notifier);
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb);
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable);
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred);
+
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision);
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
@@ -2282,7 +2274,7 @@ public:
RID render_target_create();
void render_target_set_position(RID p_render_target, int p_x, int p_y);
- void render_target_set_size(RID p_render_target, int p_width, int p_height);
+ void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count);
RID render_target_get_texture(RID p_render_target);
void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 6f29ff42bc..27305cc938 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -31,8 +31,8 @@
#include "shader_rd.h"
#include "core/io/compression.h"
-#include "core/os/dir_access.h"
-#include "core/os/file_access.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
#include "renderer_compositor_rd.h"
#include "servers/rendering/rendering_device.h"
#include "thirdparty/misc/smolv.h"
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index 2186bd174b..a443bcdcb8 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -65,7 +65,7 @@ void main() {
#elif defined(USE_ATTRIBUTES)
vec2 vertex = vertex_attrib;
- vec4 color = color_attrib;
+ vec4 color = color_attrib * draw_data.modulation;
vec2 uv = uv_attrib;
uvec4 bones = bone_attrib;
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl
index 3977f4efa0..60c881881d 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/gi.glsl
@@ -77,9 +77,9 @@ struct VoxelGIData {
bool blend_ambient;
uint texture_slot;
- float anisotropy_strength;
- float ambient_occlusion;
- float ambient_occlusion_size;
+ uint pad0;
+ uint pad1;
+ uint pad2;
uint mipmaps;
};
@@ -551,27 +551,6 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
}
}
- if (voxel_gi_instances.data[index].ambient_occlusion > 0.001) {
- float size = 1.0 + voxel_gi_instances.data[index].ambient_occlusion_size * 7.0;
-
- float taps, blend;
- blend = modf(size, taps);
- float ao = 0.0;
- for (float i = 1.0; i <= taps; i++) {
- vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size;
- ao += textureLod(sampler3D(voxel_gi_textures[index], linear_sampler_with_mipmaps), ofs, i - 1.0).a * i;
- }
-
- if (blend > 0.001) {
- vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size;
- ao += textureLod(sampler3D(voxel_gi_textures[index], linear_sampler_with_mipmaps), ofs, taps).a * (taps + 1.0) * blend;
- }
-
- ao = 1.0 - min(1.0, ao);
-
- light.rgb = mix(params.ao_color, light.rgb, mix(1.0, ao, voxel_gi_instances.data[index].ambient_occlusion));
- }
-
light.rgb *= voxel_gi_instances.data[index].dynamic_range;
if (!voxel_gi_instances.data[index].blend_ambient) {
light.a = 1.0;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 23f56fd42d..8538030263 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -850,7 +850,7 @@ void main() {
if (scene_data.roughness_limiter_enabled) {
//http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
float roughness2 = roughness * roughness;
- vec3 dndu = dFdx(normal), dndv = dFdx(normal);
+ vec3 dndu = dFdx(normal), dndv = dFdy(normal);
float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv));
float kernelRoughness2 = min(2.0 * variance, scene_data.roughness_limiter_limit); //limit effect
float filteredRoughness2 = min(1.0, roughness2 + kernelRoughness2);
@@ -904,7 +904,7 @@ void main() {
}
#endif // USE_LIGHTMAP
#if defined(CUSTOM_IRRADIANCE_USED)
- ambient_light = mix(specular_light, custom_irradiance.rgb, custom_irradiance.a);
+ ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a);
#endif
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index e64e52623e..6599a42bab 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -52,6 +52,7 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
+#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5)
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
@@ -66,8 +67,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
-#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 24)
-
layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
LightData data[];
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index d488c99b6d..aa8a0b96c5 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -96,6 +96,18 @@ layout(location = 8) out float dp_clip;
#endif
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif
+#else
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
invariant gl_Position;
#GLOBALS
@@ -234,7 +246,13 @@ void main() {
vec4 position;
#endif
+#ifdef USE_MULTIVIEW
+ mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex];
+ mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex];
+#else
mat4 projection_matrix = scene_data.projection_matrix;
+ mat4 inv_projection_matrix = scene_data.inv_projection_matrix;
+#endif //USE_MULTIVIEW
//using world coordinates
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
@@ -386,10 +404,26 @@ layout(location = 8) in float dp_clip;
#endif
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif
+#else
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
//defines to keep compatibility with vertex
#define world_matrix draw_call.transform
+#ifdef USE_MULTIVIEW
+#define projection_matrix scene_data.projection_matrix_view[ViewIndex]
+#else
#define projection_matrix scene_data.projection_matrix
+#endif
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
//both required for transmittance to be enabled
@@ -761,7 +795,7 @@ void main() {
if (scene_data.roughness_limiter_enabled) {
//http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
float roughness2 = roughness * roughness;
- vec3 dndu = dFdx(normal), dndv = dFdx(normal);
+ vec3 dndu = dFdx(normal), dndv = dFdy(normal);
float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv));
float kernelRoughness2 = min(2.0 * variance, scene_data.roughness_limiter_limit); //limit effect
float filteredRoughness2 = min(1.0, roughness2 + kernelRoughness2);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index 656a764a89..d4ebcbeec4 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -1,4 +1,9 @@
#define M_PI 3.14159265359
+#define MAX_VIEWS 2
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
#include "decal_data_inc.glsl"
@@ -46,6 +51,7 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
+#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5)
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
@@ -60,8 +66,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
-#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 24)
-
layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
LightData data[];
}
@@ -121,10 +125,13 @@ global_variables;
layout(set = 1, binding = 0, std140) uniform SceneData {
mat4 projection_matrix;
mat4 inv_projection_matrix;
-
mat4 camera_matrix;
mat4 inv_camera_matrix;
+ // only used for multiview
+ mat4 projection_matrix_view[MAX_VIEWS];
+ mat4 inv_projection_matrix_view[MAX_VIEWS];
+
vec2 viewport_size;
vec2 screen_pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl
index 9924da37d5..41c6325bc5 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/sky.glsl
@@ -4,11 +4,17 @@
#VERSION_DEFINES
+#define MAX_VIEWS 2
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
layout(location = 0) out vec2 uv_interp;
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
- vec4 proj;
+ vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
float time;
}
@@ -26,15 +32,29 @@ void main() {
#VERSION_DEFINES
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
#define M_PI 3.14159265359
+#define MAX_VIEWS 2
layout(location = 0) in vec2 uv_interp;
layout(push_constant, binding = 1, std430) uniform Params {
mat3 orientation;
- vec4 proj;
+ vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
- float time; //TODO consider adding vec2 screen res, and float radiance size
+ float time;
}
params;
@@ -85,7 +105,6 @@ struct DirectionalLightData {
layout(set = 0, binding = 3, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
-
directional_lights;
#ifdef MATERIAL_UNIFORMS_USED
@@ -154,8 +173,8 @@ vec4 fog_process(vec3 view, vec3 sky_color) {
void main() {
vec3 cube_normal;
cube_normal.z = -1.0;
- cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y;
- cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.proj.z)) / params.proj.w;
+ cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projections[ViewIndex].x)) / params.projections[ViewIndex].y;
+ cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projections[ViewIndex].z)) / params.projections[ViewIndex].w;
cube_normal = mat3(params.orientation) * cube_normal;
cube_normal.z = -cube_normal.z;
cube_normal = normalize(cube_normal);
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index 86b4da6b08..23f83b3b9c 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -4,6 +4,12 @@
#VERSION_DEFINES
+#ifdef MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#endif
+#endif
+
layout(location = 0) out vec2 uv_interp;
void main() {
@@ -18,9 +24,22 @@ void main() {
#VERSION_DEFINES
+#ifdef MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#endif //MULTIVIEW
+
layout(location = 0) in vec2 uv_interp;
+#ifdef MULTIVIEW
+layout(set = 0, binding = 0) uniform sampler2DArray source_color;
+#else
layout(set = 0, binding = 0) uniform sampler2D source_color;
+#endif
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(set = 2, binding = 0) uniform sampler2D source_glow;
#ifdef USE_1D_LUT
@@ -277,10 +296,17 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
const float FXAA_REDUCE_MUL = (1.0 / 8.0);
const float FXAA_SPAN_MAX = 8.0;
+#ifdef MULTIVIEW
+ vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+ vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+ vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+ vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure;
+#else
vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure;
+#endif
vec3 rgbM = color;
vec3 luma = vec3(0.299, 0.587, 0.114);
float lumaNW = dot(rgbNW, luma);
@@ -305,8 +331,13 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
dir * rcpDirMin)) *
params.pixel_size;
+#ifdef MULTIVIEW
+ vec3 rgbA = 0.5 * exposure * (textureLod(source_color, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz);
+ vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source_color, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz);
+#else
vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz);
+#endif
float lumaB = dot(rgbB, luma);
if ((lumaB < lumaMin) || (lumaB > lumaMax)) {
@@ -329,7 +360,11 @@ vec3 screen_space_dither(vec2 frag_coord) {
}
void main() {
+#ifdef MULTIVIEW
+ vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb;
+#else
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
+#endif
// Exposure
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 355c092dba..d2e9f64335 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -56,13 +56,14 @@ public:
virtual RID scenario_allocate() = 0;
virtual void scenario_initialize(RID p_rid) = 0;
- virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) = 0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx) = 0;
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) = 0;
virtual bool is_scenario(RID p_scenario) const = 0;
virtual RID scenario_get_environment(RID p_scenario) = 0;
+ virtual void scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport) = 0;
+ virtual void scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport) = 0;
virtual RID instance_allocate() = 0;
virtual void instance_initialize(RID p_rid) = 0;
@@ -79,9 +80,9 @@ public:
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb) = 0;
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0;
- virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0;
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0;
+ virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance) = 0;
// don't use these in a game!
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0;
@@ -92,8 +93,7 @@ public:
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) = 0;
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
- virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
- virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0;
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0;
@@ -189,7 +189,7 @@ public:
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
@@ -201,11 +201,11 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
- virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas) = 0;
- virtual void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas) = 0;
+ virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface) = 0;
virtual void update() = 0;
virtual void render_probes() = 0;
+ virtual void update_visibility_notifiers() = 0;
virtual bool free(RID p_rid) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index a001aea5f4..2e148fefcf 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -43,7 +43,7 @@ RID RendererSceneCull::camera_allocate() {
return camera_owner.allocate_rid();
}
void RendererSceneCull::camera_initialize(RID p_rid) {
- camera_owner.initialize_rid(p_rid, memnew(Camera));
+ camera_owner.initialize_rid(p_rid);
}
void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) {
@@ -310,7 +310,9 @@ RID RendererSceneCull::scenario_allocate() {
return scenario_owner.allocate_rid();
}
void RendererSceneCull::scenario_initialize(RID p_rid) {
- Scenario *scenario = memnew(Scenario);
+ scenario_owner.initialize_rid(p_rid);
+
+ Scenario *scenario = scenario_owner.getornull(p_rid);
scenario->self = p_rid;
scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create();
@@ -323,16 +325,9 @@ void RendererSceneCull::scenario_initialize(RID p_rid) {
scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool);
scenario->instance_data.set_page_pool(&instance_data_page_pool);
+ scenario->instance_visibility.set_page_pool(&instance_visibility_data_page_pool);
RendererSceneOcclusionCull::get_singleton()->add_scenario(p_rid);
-
- scenario_owner.initialize_rid(p_rid, scenario);
-}
-
-void RendererSceneCull::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) {
- Scenario *scenario = scenario_owner.getornull(p_scenario);
- ERR_FAIL_COND(!scenario);
- scenario->debug = p_debug_mode;
}
void RendererSceneCull::scenario_set_environment(RID p_scenario, RID p_environment) {
@@ -369,6 +364,37 @@ RID RendererSceneCull::scenario_get_environment(RID p_scenario) {
return scenario->environment;
}
+void RendererSceneCull::scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport) {
+ Scenario *scenario = scenario_owner.getornull(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ if (!scenario->viewport_visibility_masks.has(p_viewport)) {
+ return;
+ }
+
+ uint64_t mask = scenario->viewport_visibility_masks[p_viewport];
+ scenario->used_viewport_visibility_bits &= ~mask;
+ scenario->viewport_visibility_masks.erase(p_viewport);
+}
+
+void RendererSceneCull::scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport) {
+ Scenario *scenario = scenario_owner.getornull(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ ERR_FAIL_COND(scenario->viewport_visibility_masks.has(p_viewport));
+
+ uint64_t new_mask = 1;
+ while (new_mask & scenario->used_viewport_visibility_bits) {
+ new_mask <<= 1;
+ }
+
+ if (new_mask == 0) {
+ ERR_PRINT("Only 64 viewports per scenario allowed when using visibility ranges.");
+ new_mask = ((uint64_t)1) << 63;
+ }
+
+ scenario->viewport_visibility_masks[p_viewport] = new_mask;
+ scenario->used_viewport_visibility_bits |= new_mask;
+}
+
/* INSTANCING API */
void RendererSceneCull::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
@@ -390,10 +416,9 @@ RID RendererSceneCull::instance_allocate() {
return instance_owner.allocate_rid();
}
void RendererSceneCull::instance_initialize(RID p_rid) {
- Instance *instance = memnew(Instance);
+ instance_owner.initialize_rid(p_rid);
+ Instance *instance = instance_owner.getornull(p_rid);
instance->self = p_rid;
-
- instance_owner.initialize_rid(p_rid, instance);
}
void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
@@ -447,7 +472,6 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
switch (instance->base_type) {
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
- case RS::INSTANCE_IMMEDIATE:
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
scene_render->geometry_instance_free(geom->geometry_instance);
@@ -474,6 +498,9 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
RSG::storage->free(collision->instance);
} break;
+ case RS::INSTANCE_VISIBLITY_NOTIFIER: {
+ //none
+ } break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
scene_render->free(reflection_probe->instance);
@@ -556,7 +583,6 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
} break;
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
- case RS::INSTANCE_IMMEDIATE:
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = memnew(InstanceGeometryData);
instance->base_data = geom;
@@ -583,6 +609,11 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
instance->base_data = collision;
} break;
+ case RS::INSTANCE_VISIBLITY_NOTIFIER: {
+ InstanceVisibilityNotifierData *vnd = memnew(InstanceVisibilityNotifierData);
+ vnd->base = p_base;
+ instance->base_data = vnd;
+ } break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
reflection_probe->owner = instance;
@@ -849,7 +880,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
}
inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
- return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE;
+ return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES;
}
void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
@@ -902,9 +933,6 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
}
}
-void RendererSceneCull::instance_set_exterior(RID p_instance, bool p_enabled) {
-}
-
void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
@@ -1103,10 +1131,142 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
}
}
-void RendererSceneCull::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
+void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
+ Instance *instance = instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ instance->visibility_range_begin = p_min;
+ instance->visibility_range_end = p_max;
+ instance->visibility_range_begin_margin = p_min_margin;
+ instance->visibility_range_end_margin = p_max_margin;
+
+ _update_instance_visibility_dependencies(instance);
+
+ if (instance->scenario && instance->visibility_index != -1) {
+ InstanceVisibilityData &vd = instance->scenario->instance_visibility[instance->visibility_index];
+ vd.range_begin = instance->visibility_range_begin;
+ vd.range_end = instance->visibility_range_end;
+ vd.range_begin_margin = instance->visibility_range_begin_margin;
+ vd.range_end_margin = instance->visibility_range_end_margin;
+ }
}
-void RendererSceneCull::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) {
+void RendererSceneCull::instance_set_visibility_parent(RID p_instance, RID p_parent_instance) {
+ Instance *instance = instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!instance);
+
+ Instance *old_parent = instance->visibility_parent;
+ if (old_parent) {
+ if ((1 << old_parent->base_type) & RS::INSTANCE_GEOMETRY_MASK && old_parent->base_data) {
+ InstanceGeometryData *old_parent_geom = static_cast<InstanceGeometryData *>(old_parent->base_data);
+ old_parent_geom->visibility_dependencies.erase(instance);
+ _update_instance_visibility_depth(old_parent);
+ }
+ instance->visibility_parent = nullptr;
+ }
+
+ Instance *parent = instance_owner.getornull(p_parent_instance);
+ ERR_FAIL_COND(p_parent_instance.is_valid() && !parent);
+
+ if (parent) {
+ if ((1 << parent->base_type) & RS::INSTANCE_GEOMETRY_MASK && parent->base_data) {
+ InstanceGeometryData *parent_geom = static_cast<InstanceGeometryData *>(parent->base_data);
+ parent_geom->visibility_dependencies.insert(instance);
+ _update_instance_visibility_depth(parent);
+ }
+ instance->visibility_parent = parent;
+ }
+
+ _update_instance_visibility_dependencies(instance);
+}
+
+void RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance) {
+ bool cycle_detected = false;
+ Set<Instance *> traversed_nodes;
+
+ {
+ Instance *instance = p_instance;
+ while (instance && ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ if (!geom->visibility_dependencies.is_empty()) {
+ uint32_t depth = 0;
+ for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
+ if (((1 << E->get()->base_type) & RS::INSTANCE_GEOMETRY_MASK) == 0 || !E->get()->base_data) {
+ continue;
+ }
+ InstanceGeometryData *child_geom = static_cast<InstanceGeometryData *>(E->get()->base_data);
+ depth = MAX(depth, child_geom->visibility_dependencies_depth);
+ }
+ geom->visibility_dependencies_depth = depth + 1;
+ } else {
+ geom->visibility_dependencies_depth = 0;
+ }
+
+ if (instance->scenario && instance->visibility_index != -1) {
+ instance->scenario->instance_visibility.move(instance->visibility_index, geom->visibility_dependencies_depth);
+ }
+
+ traversed_nodes.insert(instance);
+
+ instance = instance->visibility_parent;
+ if (traversed_nodes.has(instance)) {
+ cycle_detected = true;
+ break;
+ }
+ }
+ }
+
+ if (cycle_detected) {
+ ERR_PRINT("Cycle detected in the visibility dependecies tree.");
+ for (Set<Instance *>::Element *E = traversed_nodes.front(); E; E = E->next()) {
+ Instance *instance = E->get();
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ geom->visibility_dependencies_depth = 0;
+ if (instance->scenario && instance->visibility_index != -1) {
+ instance->scenario->instance_visibility.move(instance->visibility_index, geom->visibility_dependencies_depth);
+ }
+ }
+ }
+}
+
+void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_instance) {
+ bool is_geometry_instance = ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) && p_instance->base_data;
+ bool has_visibility_range = p_instance->visibility_range_begin > 0.0 || p_instance->visibility_range_end > 0.0;
+ bool needs_visibility_cull = has_visibility_range && is_geometry_instance && p_instance->array_index != -1;
+
+ if (!needs_visibility_cull && p_instance->visibility_index != -1) {
+ p_instance->scenario->instance_visibility.remove(p_instance->visibility_index);
+ p_instance->visibility_index = -1;
+ } else if (needs_visibility_cull && p_instance->visibility_index == -1) {
+ InstanceVisibilityData vd;
+ vd.instance = p_instance;
+ vd.range_begin = p_instance->visibility_range_begin;
+ vd.range_end = p_instance->visibility_range_end;
+ vd.range_begin_margin = p_instance->visibility_range_begin_margin;
+ vd.range_end_margin = p_instance->visibility_range_end_margin;
+ vd.position = p_instance->transformed_aabb.get_position() + p_instance->transformed_aabb.get_size() / 2.0f;
+ vd.array_index = p_instance->array_index;
+
+ InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ p_instance->scenario->instance_visibility.insert(vd, geom_data->visibility_dependencies_depth);
+ }
+
+ if (p_instance->scenario && p_instance->array_index != -1) {
+ p_instance->scenario->instance_data[p_instance->array_index].visibility_index = p_instance->visibility_index;
+
+ InstanceGeometryData *geom_data = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ if ((has_visibility_range || p_instance->visibility_parent) && (p_instance->visibility_index == -1 || (geom_data && geom_data->visibility_dependencies_depth == 0))) {
+ p_instance->scenario->instance_data[p_instance->array_index].flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
+ } else {
+ p_instance->scenario->instance_data[p_instance->array_index].flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK;
+ }
+
+ if (p_instance->visibility_parent) {
+ p_instance->scenario->instance_data[p_instance->array_index].parent_array_index = p_instance->visibility_parent->array_index;
+ } else {
+ p_instance->scenario->instance_data[p_instance->array_index].parent_array_index = -1;
+ }
+ }
}
void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) {
@@ -1352,12 +1512,22 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
idata.layer_mask = p_instance->layer_mask;
idata.flags = p_instance->base_type; //changing it means de-indexing, so this never needs to be changed later
idata.base_rid = p_instance->base;
+ idata.parent_array_index = p_instance->visibility_parent ? p_instance->visibility_parent->array_index : -1;
+ idata.visibility_index = p_instance->visibility_index;
+
switch (p_instance->base_type) {
case RS::INSTANCE_MESH:
case RS::INSTANCE_MULTIMESH:
- case RS::INSTANCE_IMMEDIATE:
case RS::INSTANCE_PARTICLES: {
- idata.instance_geometry = static_cast<InstanceGeometryData *>(p_instance->base_data)->geometry_instance;
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ idata.instance_geometry = geom->geometry_instance;
+
+ for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = p_instance->array_index;
+ }
+ }
} break;
case RS::INSTANCE_LIGHT: {
idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance.get_id();
@@ -1374,6 +1544,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
case RS::INSTANCE_VOXEL_GI: {
idata.instance_data_rid = static_cast<InstanceVoxelGIData *>(p_instance->base_data)->probe_instance.get_id();
} break;
+ case RS::INSTANCE_VISIBLITY_NOTIFIER: {
+ idata.visibility_notifier = static_cast<InstanceVisibilityNotifierData *>(p_instance->base_data);
+ } break;
default: {
}
}
@@ -1404,6 +1577,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
p_instance->scenario->instance_data.push_back(idata);
p_instance->scenario->instance_aabbs.push_back(InstanceBounds(p_instance->transformed_aabb));
+ _update_instance_visibility_dependencies(p_instance);
} else {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, bvh_aabb);
@@ -1413,6 +1587,10 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
p_instance->scenario->instance_aabbs[p_instance->array_index] = InstanceBounds(p_instance->transformed_aabb);
}
+ if (p_instance->visibility_index != -1) {
+ p_instance->scenario->instance_visibility[p_instance->visibility_index].position = p_instance->transformed_aabb.get_position() + p_instance->transformed_aabb.get_size() / 2.0f;
+ }
+
//move instance and repair
pair_pass++;
@@ -1486,9 +1664,24 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
//replace this by last
int32_t swap_with_index = p_instance->scenario->instance_data.size() - 1;
if (swap_with_index != p_instance->array_index) {
- p_instance->scenario->instance_data[swap_with_index].instance->array_index = p_instance->array_index; //swap
+ Instance *swapped_instance = p_instance->scenario->instance_data[swap_with_index].instance;
+ swapped_instance->array_index = p_instance->array_index; //swap
p_instance->scenario->instance_data[p_instance->array_index] = p_instance->scenario->instance_data[swap_with_index];
p_instance->scenario->instance_aabbs[p_instance->array_index] = p_instance->scenario->instance_aabbs[swap_with_index];
+
+ if (swapped_instance->visibility_index != -1) {
+ swapped_instance->scenario->instance_visibility[swapped_instance->visibility_index].array_index = swapped_instance->array_index;
+ }
+
+ if ((1 << swapped_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(swapped_instance->base_data);
+ for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance != p_instance && dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = swapped_instance->array_index;
+ }
+ }
+ }
}
// pop last
@@ -1505,7 +1698,16 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0);
+
+ for (Set<Instance *>::Element *E = geom->visibility_dependencies.front(); E; E = E->next()) {
+ Instance *dep_instance = E->get();
+ if (dep_instance->array_index != -1) {
+ dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
+ }
+ }
}
+
+ _update_instance_visibility_dependencies(p_instance);
}
void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
@@ -1534,14 +1736,6 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
}
} break;
- case RenderingServer::INSTANCE_IMMEDIATE: {
- if (p_instance->custom_aabb) {
- new_aabb = *p_instance->custom_aabb;
- } else {
- new_aabb = RSG::storage->immediate_get_aabb(p_instance->base);
- }
-
- } break;
case RenderingServer::INSTANCE_PARTICLES: {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
@@ -1554,6 +1748,9 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
} break;
+ case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {
+ new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
+ } break;
case RenderingServer::INSTANCE_LIGHT: {
new_aabb = RSG::storage->light_get_aabb(p_instance->base);
@@ -1680,8 +1877,6 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
- RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base);
-
real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
real_t range = max_distance - min_distance;
@@ -1841,22 +2036,13 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
}
}
- x_max_cam = x_vec.dot(center) + radius + soft_shadow_expand;
- x_min_cam = x_vec.dot(center) - radius - soft_shadow_expand;
- y_max_cam = y_vec.dot(center) + radius + soft_shadow_expand;
- y_min_cam = y_vec.dot(center) - radius - soft_shadow_expand;
-
- if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) {
- //this trick here is what stabilizes the shadow (make potential jaggies to not move)
- //at the cost of some wasted resolution. Still the quality increase is very well worth it
-
- real_t unit = radius * 2.0 / texture_size;
-
- x_max_cam = Math::snapped(x_max_cam, unit);
- x_min_cam = Math::snapped(x_min_cam, unit);
- y_max_cam = Math::snapped(y_max_cam, unit);
- y_min_cam = Math::snapped(y_min_cam, unit);
- }
+ // This trick here is what stabilizes the shadow (make potential jaggies to not move)
+ // at the cost of some wasted resolution. Still, the quality increase is very well worth it.
+ const real_t unit = radius * 2.0 / texture_size;
+ x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit);
+ x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit);
+ y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit);
+ y_min_cam = Math::snapped(y_vec.dot(center) - radius - soft_shadow_expand, unit);
}
//now that we know all ranges, we can proceed to make the light frustum planes, for culling octree
@@ -2186,153 +2372,159 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return animated_material_found;
}
-void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
-// render to mono camera
+void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface) {
#ifndef _3D_DISABLED
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
- /* STEP 1 - SETUP CAMERA */
- CameraMatrix camera_matrix;
- bool ortho = false;
-
- switch (camera->type) {
- case Camera::ORTHOGONAL: {
- camera_matrix.set_orthogonal(
- camera->size,
- p_viewport_size.width / (float)p_viewport_size.height,
- camera->znear,
- camera->zfar,
- camera->vaspect);
- ortho = true;
- } break;
- case Camera::PERSPECTIVE: {
- camera_matrix.set_perspective(
- camera->fov,
- p_viewport_size.width / (float)p_viewport_size.height,
- camera->znear,
- camera->zfar,
- camera->vaspect);
- ortho = false;
+ RendererSceneRender::CameraData camera_data;
+
+ // Setup Camera(s)
+ if (p_xr_interface.is_null()) {
+ // Normal camera
+ Transform3D transform = camera->transform;
+ CameraMatrix projection;
+ bool vaspect = camera->vaspect;
+ bool is_ortogonal = false;
+
+ switch (camera->type) {
+ case Camera::ORTHOGONAL: {
+ projection.set_orthogonal(
+ camera->size,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect);
+ is_ortogonal = true;
+ } break;
+ case Camera::PERSPECTIVE: {
+ projection.set_perspective(
+ camera->fov,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect);
- } break;
- case Camera::FRUSTUM: {
- camera_matrix.set_frustum(
- camera->size,
- p_viewport_size.width / (float)p_viewport_size.height,
- camera->offset,
- camera->znear,
- camera->zfar,
- camera->vaspect);
- ortho = false;
- } break;
+ } break;
+ case Camera::FRUSTUM: {
+ projection.set_frustum(
+ camera->size,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->offset,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect);
+ } break;
+ }
+
+ camera_data.set_camera(transform, projection, is_ortogonal, vaspect);
+ } else {
+ // Setup our camera for our XR interface.
+ // We can support multiple views here each with their own camera
+ Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS];
+ CameraMatrix projections[RendererSceneRender::MAX_RENDER_VIEWS];
+
+ uint32_t view_count = p_xr_interface->get_view_count();
+ ERR_FAIL_COND_MSG(view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported");
+
+ float aspect = p_viewport_size.width / (float)p_viewport_size.height;
+
+ Transform3D world_origin = XRServer::get_singleton()->get_world_origin();
+
+ // We ignore our camera position, it will have been positioned with a slightly old tracking position.
+ // Instead we take our origin point and have our XR interface add fresh tracking data! Whoohoo!
+ for (uint32_t v = 0; v < view_count; v++) {
+ transforms[v] = p_xr_interface->get_transform_for_view(v, world_origin);
+ projections[v] = p_xr_interface->get_projection_for_view(v, aspect, camera->znear, camera->zfar);
+ }
+
+ if (view_count == 1) {
+ camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect);
+ } else if (view_count == 2) {
+ camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect);
+ } else {
+ // this won't be called (see fail check above) but keeping this comment to indicate we may support more then 2 views in the future...
+ }
}
RID environment = _render_get_environment(p_camera, p_scenario);
RENDER_TIMESTAMP("Update occlusion buffer")
- RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera->transform, camera_matrix, ortho, RendererThreadPool::singleton->thread_work_pool);
+ // For now just cull on the first camera
+ RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_ortogonal, RendererThreadPool::singleton->thread_work_pool);
- _render_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
+ _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
#endif
}
-void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) {
- // render for AR/VR interface
-#if 0
- Camera *camera = camera_owner.getornull(p_camera);
- ERR_FAIL_COND(!camera);
+void RendererSceneCull::_visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data) {
+ uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t bin_from = p_thread * cull_data->cull_count / total_threads;
+ uint32_t bin_to = (p_thread + 1 == total_threads) ? cull_data->cull_count : ((p_thread + 1) * cull_data->cull_count / total_threads);
+
+ _visibility_cull(*cull_data, cull_data->cull_offset + bin_from, cull_data->cull_offset + bin_to);
+}
- /* SETUP CAMERA, we are ignoring type and FOV here */
- float aspect = p_viewport_size.width / (float)p_viewport_size.height;
- CameraMatrix camera_matrix = p_interface->get_projection_for_eye(p_eye, aspect, camera->znear, camera->zfar);
+void RendererSceneCull::_visibility_cull(const VisibilityCullData &cull_data, uint64_t p_from, uint64_t p_to) {
+ Scenario *scenario = cull_data.scenario;
+ for (unsigned int i = p_from; i < p_to; i++) {
+ InstanceVisibilityData &vd = scenario->instance_visibility[i];
+ InstanceData &idata = scenario->instance_data[vd.array_index];
- // We also ignore our camera position, it will have been positioned with a slightly old tracking position.
- // Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo!
- Transform3D world_origin = XRServer::get_singleton()->get_world_origin();
- Transform3D cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin);
+ if (idata.parent_array_index >= 0) {
+ uint32_t parent_flags = scenario->instance_data[idata.parent_array_index].flags;
+ if ((parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN) || (parent_flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE) == 0) {
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ continue;
+ }
+ }
- RID environment = _render_get_environment(p_camera, p_scenario);
+ int range_check = _visibility_range_check(vd, cull_data.camera_position, cull_data.viewport_mask);
- // For stereo render we only prepare for our left eye and then reuse the outcome for our right eye
- if (p_eye == XRInterface::EYE_LEFT) {
- // Center our transform, we assume basis is equal.
- Transform3D mono_transform = cam_transform;
- Transform3D right_transform = p_interface->get_transform_for_eye(XRInterface::EYE_RIGHT, world_origin);
- mono_transform.origin += right_transform.origin;
- mono_transform.origin *= 0.5;
-
- // We need to combine our projection frustums for culling.
- // Ideally we should use our clipping planes for this and combine them,
- // however our shadow map logic uses our projection matrix.
- // Note: as our left and right frustums should be mirrored, we don't need our right projection matrix.
-
- // - get some base values we need
- float eye_dist = (mono_transform.origin - cam_transform.origin).length();
- float z_near = camera_matrix.get_z_near(); // get our near plane
- float z_far = camera_matrix.get_z_far(); // get our far plane
- float width = (2.0 * z_near) / camera_matrix.matrix[0][0];
- float x_shift = width * camera_matrix.matrix[2][0];
- float height = (2.0 * z_near) / camera_matrix.matrix[1][1];
- float y_shift = height * camera_matrix.matrix[2][1];
-
- // printf("Eye_dist = %f, Near = %f, Far = %f, Width = %f, Shift = %f\n", eye_dist, z_near, z_far, width, x_shift);
-
- // - calculate our near plane size (horizontal only, right_near is mirrored)
- float left_near = -eye_dist - ((width - x_shift) * 0.5);
-
- // - calculate our far plane size (horizontal only, right_far is mirrored)
- float left_far = -eye_dist - (z_far * (width - x_shift) * 0.5 / z_near);
- float left_far_right_eye = eye_dist - (z_far * (width + x_shift) * 0.5 / z_near);
- if (left_far > left_far_right_eye) {
- // on displays smaller then double our iod, the right eye far frustrum can overtake the left eyes.
- left_far = left_far_right_eye;
- }
-
- // - figure out required z-shift
- float slope = (left_far - left_near) / (z_far - z_near);
- float z_shift = (left_near / slope) - z_near;
-
- // - figure out new vertical near plane size (this will be slightly oversized thanks to our z-shift)
- float top_near = (height - y_shift) * 0.5;
- top_near += (top_near / z_near) * z_shift;
- float bottom_near = -(height + y_shift) * 0.5;
- bottom_near += (bottom_near / z_near) * z_shift;
-
- // printf("Left_near = %f, Left_far = %f, Top_near = %f, Bottom_near = %f, Z_shift = %f\n", left_near, left_far, top_near, bottom_near, z_shift);
-
- // - generate our frustum
- CameraMatrix combined_matrix;
- combined_matrix.set_frustum(left_near, -left_near, bottom_near, top_near, z_near + z_shift, z_far + z_shift);
-
- // and finally move our camera back
- Transform3D apply_z_shift;
- apply_z_shift.origin = Vector3(0.0, 0.0, z_shift); // z negative is forward so this moves it backwards
- mono_transform *= apply_z_shift;
-
- // now prepare our scene with our adjusted transform projection matrix
- _prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
- } else if (p_eye == XRInterface::EYE_MONO) {
- // For mono render, prepare as per usual
- _prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold);
- }
-
- // And render our scene...
- _render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
-#endif
-};
+ if (range_check == -1) {
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ } else if (range_check == 1) {
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
+ idata.flags |= InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ } else {
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN;
+ idata.flags &= ~InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE;
+ }
+ }
+}
+
+int RendererSceneCull::_visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask) {
+ float dist = p_camera_pos.distance_to(r_vis_data.position);
+
+ bool in_range_last_frame = p_viewport_mask & r_vis_data.viewport_state;
+ float begin_offset = in_range_last_frame ? -r_vis_data.range_begin_margin : r_vis_data.range_begin_margin;
+ float end_offset = in_range_last_frame ? r_vis_data.range_end_margin : -r_vis_data.range_end_margin;
+
+ if (r_vis_data.range_end > 0.0f && dist > r_vis_data.range_end + end_offset) {
+ r_vis_data.viewport_state &= ~p_viewport_mask;
+ return -1;
+ } else if (r_vis_data.range_begin > 0.0f && dist < r_vis_data.range_begin + begin_offset) {
+ r_vis_data.viewport_state &= ~p_viewport_mask;
+ return 1;
+ } else {
+ r_vis_data.viewport_state |= p_viewport_mask;
+ return 0;
+ }
+}
-void RendererSceneCull::_frustum_cull_threaded(uint32_t p_thread, CullData *cull_data) {
+void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {
uint32_t cull_total = cull_data->scenario->instance_data.size();
uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
uint32_t cull_from = p_thread * cull_total / total_threads;
uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads);
- _frustum_cull(*cull_data, frustum_cull_result_threads[p_thread], cull_from, cull_to);
+ _scene_cull(*cull_data, scene_cull_result_threads[p_thread], cull_from, cull_to);
}
-void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to) {
+void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to) {
uint64_t frame_number = RSG::rasterizer->get_frame_number();
float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
@@ -2347,177 +2539,201 @@ void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cu
for (uint64_t i = p_from; i < p_to; i++) {
bool mesh_visible = false;
- if (cull_data.scenario->instance_aabbs[i].in_frustum(cull_data.cull->frustum) && (cull_data.occlusion_buffer == nullptr || cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING ||
- !cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))) {
- InstanceData &idata = cull_data.scenario->instance_data[i];
- uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
-
- if ((cull_data.visible_layers & idata.layer_mask) == 0) {
- //failure
- } else if (base_type == RS::INSTANCE_LIGHT) {
- cull_result.lights.push_back(idata.instance);
- cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));
- if (cull_data.shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
- scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
- }
+ InstanceData &idata = cull_data.scenario->instance_data[i];
+ uint32_t visibility_flags = idata.flags & (InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE | InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN);
+ int32_t visibility_check = -1;
- } else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
- if (cull_data.render_reflection_probe != idata.instance) {
- //avoid entering The Matrix
+#define HIDDEN_BY_VISIBILITY_CHECKS (visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE || visibility_flags == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN)
+#define LAYER_CHECK (cull_data.visible_layers & idata.layer_mask)
+#define IN_FRUSTUM(f) (cull_data.scenario->instance_aabbs[i].in_frustum(f))
+#define VIS_RANGE_CHECK ((idata.visibility_index == -1) || _visibility_range_check(cull_data.scenario->instance_visibility[idata.visibility_index], cull_data.cam_transform.origin, cull_data.visibility_viewport_mask) == 0)
+#define VIS_PARENT_CHECK ((idata.parent_array_index == -1) || ((cull_data.scenario->instance_data[idata.parent_array_index].flags & InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK) == InstanceData::FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE))
+#define VIS_CHECK (visibility_check < 0 ? (visibility_check = (visibility_flags != InstanceData::FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK || (VIS_RANGE_CHECK && VIS_PARENT_CHECK))) : visibility_check)
+#define OCCLUSION_CULLED (cull_data.occlusion_buffer != nullptr && (cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_IGNORE_OCCLUSION_CULLING) == 0 && cull_data.occlusion_buffer->is_occluded(cull_data.scenario->instance_aabbs[i].bounds, cull_data.cam_transform.origin, inv_cam_transform, *cull_data.camera_matrix, z_near))
- if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {
- InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
- cull_data.cull->lock.lock();
- if (!reflection_probe->update_list.in_list()) {
- reflection_probe->render_step = 0;
- reflection_probe_render_list.add_last(&reflection_probe->update_list);
- }
- cull_data.cull->lock.unlock();
-
- idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
+ if (!HIDDEN_BY_VISIBILITY_CHECKS) {
+ if (LAYER_CHECK && IN_FRUSTUM(cull_data.cull->frustum) && VIS_CHECK && !OCCLUSION_CULLED) {
+ uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
+ if (base_type == RS::INSTANCE_LIGHT) {
+ cull_result.lights.push_back(idata.instance);
+ cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));
+ if (cull_data.shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
+ scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
}
- if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {
- cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid));
- }
- }
- } else if (base_type == RS::INSTANCE_DECAL) {
- cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid));
+ } else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
+ if (cull_data.render_reflection_probe != idata.instance) {
+ //avoid entering The Matrix
- } else if (base_type == RS::INSTANCE_VOXEL_GI) {
- InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(idata.instance->base_data);
- cull_data.cull->lock.lock();
- if (!voxel_gi->update_element.in_list()) {
- voxel_gi_update_list.add(&voxel_gi->update_element);
- }
- cull_data.cull->lock.unlock();
- cull_result.voxel_gi_instances.push_back(RID::from_uint64(idata.instance_data_rid));
+ if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
+ cull_data.cull->lock.lock();
+ if (!reflection_probe->update_list.in_list()) {
+ reflection_probe->render_step = 0;
+ reflection_probe_render_list.add_last(&reflection_probe->update_list);
+ }
+ cull_data.cull->lock.unlock();
- } else if (base_type == RS::INSTANCE_LIGHTMAP) {
- cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));
- } else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
- bool keep = true;
+ idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
+ }
- if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) {
- RenderingServerDefault::redraw_request();
- }
+ if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {
+ cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid));
+ }
+ }
+ } else if (base_type == RS::INSTANCE_DECAL) {
+ cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid));
+
+ } else if (base_type == RS::INSTANCE_VOXEL_GI) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(idata.instance->base_data);
+ cull_data.cull->lock.lock();
+ if (!voxel_gi->update_element.in_list()) {
+ voxel_gi_update_list.add(&voxel_gi->update_element);
+ }
+ cull_data.cull->lock.unlock();
+ cull_result.voxel_gi_instances.push_back(RID::from_uint64(idata.instance_data_rid));
+
+ } else if (base_type == RS::INSTANCE_LIGHTMAP) {
+ cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));
+ } else if (base_type == RS::INSTANCE_VISIBLITY_NOTIFIER) {
+ InstanceVisibilityNotifierData *vnd = idata.visibility_notifier;
+ if (!vnd->list_element.in_list()) {
+ visible_notifier_list_lock.lock();
+ visible_notifier_list.add(&vnd->list_element);
+ visible_notifier_list_lock.unlock();
+ vnd->just_visible = true;
+ }
+ vnd->visible_in_frame = RSG::rasterizer->get_frame_number();
+ } else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
+ bool keep = true;
- if (base_type == RS::INSTANCE_MESH) {
- mesh_visible = true;
- } else if (base_type == RS::INSTANCE_PARTICLES) {
- //particles visible? process them
- if (RSG::storage->particles_is_inactive(idata.base_rid)) {
- //but if nothing is going on, don't do it.
- keep = false;
- } else {
- cull_data.cull->lock.lock();
- RSG::storage->particles_request_process(idata.base_rid);
- cull_data.cull->lock.unlock();
- RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
- //particles visible? request redraw
+ if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) {
RenderingServerDefault::redraw_request();
}
- }
-
- if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
- InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
- instance_pair_buffer[idx++] = light->instance;
- if (idx == MAX_INSTANCE_PAIRS) {
- break;
+ if (base_type == RS::INSTANCE_MESH) {
+ mesh_visible = true;
+ } else if (base_type == RS::INSTANCE_PARTICLES) {
+ //particles visible? process them
+ if (RSG::storage->particles_is_inactive(idata.base_rid)) {
+ //but if nothing is going on, don't do it.
+ keep = false;
+ } else {
+ cull_data.cull->lock.lock();
+ RSG::storage->particles_request_process(idata.base_rid);
+ cull_data.cull->lock.unlock();
+ RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
+ //particles visible? request redraw
+ RenderingServerDefault::redraw_request();
}
}
- scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
- }
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
+
+ for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
+ InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
+ instance_pair_buffer[idx++] = light->instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
+ }
+
+ scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
+ }
- if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- uint32_t idx = 0;
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
- InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
+ for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
- instance_pair_buffer[idx++] = reflection_probe->instance;
- if (idx == MAX_INSTANCE_PAIRS) {
- break;
+ instance_pair_buffer[idx++] = reflection_probe->instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
}
- }
- scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
- }
+ scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
+ }
- if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- uint32_t idx = 0;
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) {
- InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->get()->base_data);
+ for (Set<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->get()->base_data);
- instance_pair_buffer[idx++] = decal->instance;
- if (idx == MAX_INSTANCE_PAIRS) {
- break;
+ instance_pair_buffer[idx++] = decal->instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
}
+ scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
}
- scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx);
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
- }
- if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- uint32_t idx = 0;
- for (Set<Instance *>::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) {
- InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->get()->base_data);
+ if (idata.flags & InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
+ for (Set<Instance *>::Element *E = geom->voxel_gi_instances.front(); E; E = E->next()) {
+ InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(E->get()->base_data);
- instance_pair_buffer[idx++] = voxel_gi->probe_instance;
- if (idx == MAX_INSTANCE_PAIRS) {
- break;
+ instance_pair_buffer[idx++] = voxel_gi->probe_instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
}
- }
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
- }
+ scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
+ }
- if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- Color *sh = idata.instance->lightmap_sh.ptrw();
- const Color *target_sh = idata.instance->lightmap_target_sh.ptr();
- for (uint32_t j = 0; j < 9; j++) {
- sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
+ if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ Color *sh = idata.instance->lightmap_sh.ptrw();
+ const Color *target_sh = idata.instance->lightmap_target_sh.ptr();
+ for (uint32_t j = 0; j < 9; j++) {
+ sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
+ }
+ scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
+ idata.instance->last_frame_pass = frame_number;
}
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
- idata.instance->last_frame_pass = frame_number;
- }
- if (keep) {
- cull_result.geometry_instances.push_back(idata.instance_geometry);
+ if (keep) {
+ cull_result.geometry_instances.push_back(idata.instance_geometry);
+ }
}
}
- }
- for (uint32_t j = 0; j < cull_data.cull->shadow_count; j++) {
- for (uint32_t k = 0; k < cull_data.cull->shadows[j].cascade_count; k++) {
- if (cull_data.scenario->instance_aabbs[i].in_frustum(cull_data.cull->shadows[j].cascades[k].frustum)) {
- InstanceData &idata = cull_data.scenario->instance_data[i];
- uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
+ for (uint32_t j = 0; j < cull_data.cull->shadow_count; j++) {
+ for (uint32_t k = 0; k < cull_data.cull->shadows[j].cascade_count; k++) {
+ if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) {
+ uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
- if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) {
- cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
- mesh_visible = true;
+ if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) {
+ cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
+ mesh_visible = true;
+ }
}
}
}
}
+#undef HIDDEN_BY_VISIBILITY_CHECKS
+#undef LAYER_CHECK
+#undef IN_FRUSTUM
+#undef VIS_RANGE_CHECK
+#undef VIS_PARENT_CHECK
+#undef VIS_CHECK
+#undef OCCLUSION_CULLED
+
for (uint32_t j = 0; j < cull_data.cull->sdfgi.region_count; j++) {
if (cull_data.scenario->instance_aabbs[i].in_aabb(cull_data.cull->sdfgi.region_aabb[j])) {
- InstanceData &idata = cull_data.scenario->instance_data[i];
uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
if (base_type == RS::INSTANCE_LIGHT) {
@@ -2544,11 +2760,7 @@ void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cu
}
}
-void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows) {
- // Note, in stereo rendering:
- // - p_cam_transform will be a transform in the middle of our two eyes
- // - p_cam_projection is a wider frustrum that encompasses both eyes
-
+void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows) {
Instance *render_reflection_probe = instance_owner.getornull(p_reflection_probe); //if null, not rendering to it
Scenario *scenario = scenario_owner.getornull(p_scenario);
@@ -2559,16 +2771,44 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
if (p_render_buffers.is_valid()) {
//no rendering code here, this is only to set up what needs to be done, request regions, etc.
- scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not)
+ scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not)
+ }
+
+ RENDER_TIMESTAMP("Visibility Dependencies");
+
+ if (scenario->instance_visibility.get_bin_count() > 0) {
+ if (!scenario->viewport_visibility_masks.has(p_viewport)) {
+ scenario_add_viewport_visibility_mask(scenario->self, p_viewport);
+ }
+
+ VisibilityCullData visibility_cull_data;
+ visibility_cull_data.scenario = scenario;
+ visibility_cull_data.viewport_mask = scenario->viewport_visibility_masks[p_viewport];
+ visibility_cull_data.camera_position = p_camera_data->main_transform.origin;
+
+ for (int i = scenario->instance_visibility.get_bin_count() - 1; i > 0; i--) { // We skip bin 0
+ visibility_cull_data.cull_offset = scenario->instance_visibility.get_bin_start(i);
+ visibility_cull_data.cull_count = scenario->instance_visibility.get_bin_size(i);
+
+ if (visibility_cull_data.cull_count == 0) {
+ continue;
+ }
+
+ if (visibility_cull_data.cull_count > thread_cull_threshold) {
+ RendererThreadPool::singleton->thread_work_pool.do_work(RendererThreadPool::singleton->thread_work_pool.get_thread_count(), this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data);
+ } else {
+ _visibility_cull(visibility_cull_data, visibility_cull_data.cull_offset, visibility_cull_data.cull_offset + visibility_cull_data.cull_count);
+ }
+ }
}
- RENDER_TIMESTAMP("Frustum Culling");
+ RENDER_TIMESTAMP("Culling");
- //rasterizer->set_camera(camera->transform, camera_matrix,ortho);
+ //rasterizer->set_camera(p_camera_data->main_transform, p_camera_data.main_projection, p_camera_data.is_ortogonal);
- Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
+ Vector<Plane> planes = p_camera_data->main_projection.get_projection_planes(p_camera_data->main_transform);
- Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized());
+ Plane near_plane(p_camera_data->main_transform.origin, -p_camera_data->main_transform.basis.get_axis(2).normalized());
/* STEP 2 - CULL */
@@ -2606,7 +2846,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
scene_render->set_directional_shadow_count(lights_with_shadow.size());
for (int i = 0; i < lights_with_shadow.size(); i++) {
- _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect);
+ _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect);
}
}
@@ -2635,7 +2875,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
}
}
- frustum_cull_result.clear();
+ scene_cull_result.clear();
{
uint64_t cull_from = 0;
@@ -2647,30 +2887,31 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
cull_data.cull = &cull;
cull_data.scenario = scenario;
cull_data.shadow_atlas = p_shadow_atlas;
- cull_data.cam_transform = p_cam_transform;
+ cull_data.cam_transform = p_camera_data->main_transform;
cull_data.visible_layers = p_visible_layers;
cull_data.render_reflection_probe = render_reflection_probe;
cull_data.occlusion_buffer = RendererSceneOcclusionCull::get_singleton()->buffer_get_ptr(p_viewport);
- cull_data.camera_matrix = &p_cam_projection;
+ cull_data.camera_matrix = &p_camera_data->main_projection;
+ cull_data.visibility_viewport_mask = scenario->viewport_visibility_masks.has(p_viewport) ? scenario->viewport_visibility_masks[p_viewport] : 0;
//#define DEBUG_CULL_TIME
#ifdef DEBUG_CULL_TIME
uint64_t time_from = OS::get_singleton()->get_ticks_usec();
#endif
if (cull_to > thread_cull_threshold) {
//multiple threads
- for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
- frustum_cull_result_threads[i].clear();
+ for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
+ scene_cull_result_threads[i].clear();
}
- RendererThreadPool::singleton->thread_work_pool.do_work(frustum_cull_result_threads.size(), this, &RendererSceneCull::_frustum_cull_threaded, &cull_data);
+ RendererThreadPool::singleton->thread_work_pool.do_work(scene_cull_result_threads.size(), this, &RendererSceneCull::_scene_cull_threaded, &cull_data);
- for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
- frustum_cull_result.append_from(frustum_cull_result_threads[i]);
+ for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
+ scene_cull_result.append_from(scene_cull_result_threads[i]);
}
} else {
//single threaded
- _frustum_cull(cull_data, frustum_cull_result, cull_from, cull_to);
+ _scene_cull(cull_data, scene_cull_result, cull_from, cull_to);
}
#ifdef DEBUG_CULL_TIME
@@ -2681,9 +2922,9 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
print_line("time taken: " + rtos(time_avg / time_count));
#endif
- if (frustum_cull_result.mesh_instances.size()) {
- for (uint64_t i = 0; i < frustum_cull_result.mesh_instances.size(); i++) {
- RSG::storage->mesh_instance_check_for_update(frustum_cull_result.mesh_instances[i]);
+ if (scene_cull_result.mesh_instances.size()) {
+ for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) {
+ RSG::storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);
}
RSG::storage->update_mesh_instances();
}
@@ -2707,14 +2948,14 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
}
render_shadow_data[max_shadows_used].light = cull.shadows[i].light_instance;
render_shadow_data[max_shadows_used].pass = j;
- render_shadow_data[max_shadows_used].instances.merge_unordered(frustum_cull_result.directional_shadows[i].cascade_geometry_instances[j]);
+ render_shadow_data[max_shadows_used].instances.merge_unordered(scene_cull_result.directional_shadows[i].cascade_geometry_instances[j]);
max_shadows_used++;
}
}
// Positional Shadowss
- for (uint32_t i = 0; i < (uint32_t)frustum_cull_result.lights.size(); i++) {
- Instance *ins = frustum_cull_result.lights[i];
+ for (uint32_t i = 0; i < (uint32_t)scene_cull_result.lights.size(); i++) {
+ Instance *ins = scene_cull_result.lights[i];
if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
continue;
@@ -2726,12 +2967,12 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
{ //compute coverage
- Transform3D cam_xf = p_cam_transform;
- float zn = p_cam_projection.get_z_near();
+ Transform3D cam_xf = p_camera_data->main_transform;
+ float zn = p_camera_data->main_projection.get_z_near();
Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane
// near plane half width and height
- Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents();
+ Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
switch (RSG::storage->light_get_type(ins->base)) {
case RS::LIGHT_OMNI: {
@@ -2743,7 +2984,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
ins->transform.origin + cam_xf.basis.get_axis(0) * radius
};
- if (!p_cam_orthogonal) {
+ if (!p_camera_data->is_ortogonal) {
//if using perspetive, map them to near plane
for (int j = 0; j < 2; j++) {
if (p.distance_to(points[j]) < 0) {
@@ -2771,7 +3012,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
base + cam_xf.basis.get_axis(0) * w
};
- if (!p_cam_orthogonal) {
+ if (!p_camera_data->is_ortogonal) {
//if using perspetive, map them to near plane
for (int j = 0; j < 2; j++) {
if (p.distance_to(points[j]) < 0) {
@@ -2802,7 +3043,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {
//must redraw!
RENDER_TIMESTAMP(">Rendering Light " + itos(i));
- light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
+ light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_ortogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold);
RENDER_TIMESTAMP("<Rendering Light " + itos(i));
} else {
light->shadow_dirty = redraw;
@@ -2818,13 +3059,13 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
if (cull.sdfgi.region_count > 0) {
//update regions
for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
- render_sdfgi_data[i].instances.merge_unordered(frustum_cull_result.sdfgi_region_geometry_instances[i]);
+ render_sdfgi_data[i].instances.merge_unordered(scene_cull_result.sdfgi_region_geometry_instances[i]);
render_sdfgi_data[i].region = i;
}
//check if static lights were culled
bool static_lights_culled = false;
for (uint32_t i = 0; i < cull.sdfgi.cascade_light_count; i++) {
- if (frustum_cull_result.sdfgi_cascade_lights[i].size()) {
+ if (scene_cull_result.sdfgi_cascade_lights[i].size()) {
static_lights_culled = true;
break;
}
@@ -2833,7 +3074,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
if (static_lights_culled) {
sdfgi_update_data.static_cascade_count = cull.sdfgi.cascade_light_count;
sdfgi_update_data.static_cascade_indices = cull.sdfgi.cascade_light_index;
- sdfgi_update_data.static_positional_lights = frustum_cull_result.sdfgi_cascade_lights;
+ sdfgi_update_data.static_positional_lights = scene_cull_result.sdfgi_cascade_lights;
sdfgi_update_data.update_static = true;
}
}
@@ -2847,7 +3088,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
//append the directional lights to the lights culled
for (int i = 0; i < directional_lights.size(); i++) {
- frustum_cull_result.light_instances.push_back(directional_lights[i]);
+ scene_cull_result.light_instances.push_back(directional_lights[i]);
}
RID camera_effects;
@@ -2864,7 +3105,7 @@ void RendererSceneCull::_render_scene(const Transform3D &p_cam_transform, const
}
RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, frustum_cull_result.geometry_instances, frustum_cull_result.light_instances, frustum_cull_result.reflections, frustum_cull_result.voxel_gi_instances, frustum_cull_result.decals, frustum_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data);
+ scene_render->render_scene(p_render_buffers, p_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data);
for (uint32_t i = 0; i < max_shadows_used; i++) {
render_shadow_data[i].instances.clear();
@@ -2911,7 +3152,11 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
environment = scenario->fallback_environment;
}
RENDER_TIMESTAMP("Render Empty Scene ");
- scene_render->render_scene(p_render_buffers, Transform3D(), CameraMatrix(), true, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+
+ RendererSceneRender::CameraData camera_data;
+ camera_data.set_camera(Transform3D(), CameraMatrix(), true, false);
+
+ scene_render->render_scene(p_render_buffers, &camera_data, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -2981,7 +3226,10 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
}
RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step));
- _render_scene(xform, cm, false, false, RID(), environment, RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, lod_threshold, use_shadows);
+ RendererSceneRender::CameraData camera_data;
+ camera_data.set_camera(xform, cm, false, false);
+
+ _render_scene(&camera_data, RID(), environment, RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, lod_threshold, use_shadows);
} else {
//do roughness postprocess step until it believes it's done
@@ -3192,7 +3440,7 @@ void RendererSceneCull::render_probes() {
update_lights = true;
}
- frustum_cull_result.geometry_instances.clear();
+ scene_cull_result.geometry_instances.clear();
RID instance_pair_buffer[MAX_INSTANCE_PAIRS];
@@ -3219,10 +3467,10 @@ void RendererSceneCull::render_probes() {
ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
- frustum_cull_result.geometry_instances.push_back(geom->geometry_instance);
+ scene_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
- scene_render->voxel_gi_update(probe->probe_instance, update_lights, probe->light_instances, frustum_cull_result.geometry_instances);
+ scene_render->voxel_gi_update(probe->probe_instance, update_lights, probe->light_instances, scene_cull_result.geometry_instances);
voxel_gi_update_list.remove(voxel_gi);
@@ -3237,7 +3485,7 @@ void RendererSceneCull::render_particle_colliders() {
if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
//update heightfield
instance_cull_result.clear();
- frustum_cull_result.geometry_instances.clear();
+ scene_cull_result.geometry_instances.clear();
struct CullAABB {
PagedArray<Instance *> *result;
@@ -3259,10 +3507,10 @@ void RendererSceneCull::render_particle_colliders() {
continue;
}
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- frustum_cull_result.geometry_instances.push_back(geom->geometry_instance);
+ scene_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
- scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, frustum_cull_result.geometry_instances);
+ scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, scene_cull_result.geometry_instances);
}
heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front());
}
@@ -3402,25 +3650,6 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
RSG::storage->base_update_dependency(mesh, &p_instance->dependency_tracker);
}
- } else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) {
- RID mat = RSG::storage->immediate_get_material(p_instance->base);
-
- if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) {
- can_cast_shadows = false;
- }
-
- if (mat.is_valid() && RSG::storage->material_is_animated(mat)) {
- is_animated = true;
- }
-
- if (mat.is_valid()) {
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
- }
-
- if (mat.is_valid()) {
- RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
- }
-
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
bool cast_shadows = false;
@@ -3538,10 +3767,7 @@ bool RendererSceneCull::free(RID p_rid) {
}
if (camera_owner.owns(p_rid)) {
- Camera *camera = camera_owner.getornull(p_rid);
-
camera_owner.free(p_rid);
- memdelete(camera);
} else if (scenario_owner.owns(p_rid)) {
Scenario *scenario = scenario_owner.getornull(p_rid);
@@ -3551,12 +3777,12 @@ bool RendererSceneCull::free(RID p_rid) {
}
scenario->instance_aabbs.reset();
scenario->instance_data.reset();
+ scenario->instance_visibility.reset();
scene_render->free(scenario->reflection_probe_shadow_atlas);
scene_render->free(scenario->reflection_atlas);
scenario_owner.free(p_rid);
RendererSceneOcclusionCull::get_singleton()->remove_scenario(p_rid);
- memdelete(scenario);
} else if (RendererSceneOcclusionCull::get_singleton()->is_occluder(p_rid)) {
RendererSceneOcclusionCull::get_singleton()->free_occluder(p_rid);
@@ -3580,7 +3806,6 @@ bool RendererSceneCull::free(RID p_rid) {
update_dirty_instances(); //in case something changed this
instance_owner.free(p_rid);
- memdelete(instance);
} else {
return false;
}
@@ -3592,6 +3817,28 @@ TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const Vector<RI
return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);
}
+void RendererSceneCull::update_visibility_notifiers() {
+ SelfList<InstanceVisibilityNotifierData> *E = visible_notifier_list.first();
+ while (E) {
+ SelfList<InstanceVisibilityNotifierData> *N = E->next();
+
+ InstanceVisibilityNotifierData *visibility_notifier = E->self();
+ if (visibility_notifier->just_visible) {
+ visibility_notifier->just_visible = false;
+
+ RSG::storage->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);
+ } else {
+ if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {
+ visible_notifier_list.remove(E);
+
+ RSG::storage->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);
+ }
+ }
+
+ E = N;
+ }
+}
+
/*******************************/
/* Passthrough to Scene Render */
/*******************************/
@@ -3619,10 +3866,10 @@ RendererSceneCull::RendererSceneCull() {
render_sdfgi_data[i].instances.set_page_pool(&geometry_instance_cull_page_pool);
}
- frustum_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
- frustum_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
- for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
- frustum_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
+ scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
+ scene_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
+ scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
}
indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");
@@ -3643,11 +3890,11 @@ RendererSceneCull::~RendererSceneCull() {
render_sdfgi_data[i].instances.reset();
}
- frustum_cull_result.reset();
- for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
- frustum_cull_result_threads[i].reset();
+ scene_cull_result.reset();
+ for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
+ scene_cull_result_threads[i].reset();
}
- frustum_cull_result_threads.clear();
+ scene_cull_result_threads.clear();
if (dummy_occlusion_culling) {
memdelete(dummy_occlusion_culling);
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index f10eb67828..53fb197fcc 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -31,6 +31,7 @@
#ifndef RENDERING_SERVER_SCENE_CULL_H
#define RENDERING_SERVER_SCENE_CULL_H
+#include "core/templates/bin_sorted_array.h"
#include "core/templates/pass_func.h"
#include "servers/rendering/renderer_compositor.h"
@@ -96,7 +97,7 @@ public:
}
};
- mutable RID_PtrOwner<Camera, true> camera_owner;
+ mutable RID_Owner<Camera, true> camera_owner;
virtual RID camera_allocate();
virtual void camera_initialize(RID p_rid);
@@ -117,6 +118,8 @@ public:
virtual void occluder_initialize(RID p_occluder);
virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices);
+ /* VISIBILITY NOTIFIER API */
+
RendererSceneOcclusionCull *dummy_occlusion_culling;
/* SCENARIO API */
@@ -242,6 +245,8 @@ public:
}
};
+ struct InstanceVisibilityNotifierData;
+
struct InstanceData {
// Store instance pointer as well as common instance processing information,
// to make processing more cache friendly.
@@ -259,6 +264,9 @@ public:
FLAG_USES_MESH_INSTANCE = (1 << 17),
FLAG_REFLECTION_PROBE_DIRTY = (1 << 18),
FLAG_IGNORE_OCCLUSION_CULLING = (1 << 19),
+ FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK = (3 << 20), // 2 bits, overlaps with the other vis. dependency flags
+ FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE = (1 << 20),
+ FLAG_VISIBILITY_DEPENDENCY_HIDDEN = (1 << 21),
};
uint32_t flags = 0;
@@ -267,12 +275,36 @@ public:
union {
uint64_t instance_data_rid;
RendererSceneRender::GeometryInstance *instance_geometry;
+ InstanceVisibilityNotifierData *visibility_notifier;
};
Instance *instance = nullptr;
+ int32_t parent_array_index = -1;
+ int32_t visibility_index = -1;
+ };
+
+ struct InstanceVisibilityData {
+ uint64_t viewport_state = 0;
+ int32_t array_index = -1;
+ Vector3 position;
+ Instance *instance = nullptr;
+ float range_begin = 0.0f;
+ float range_end = 0.0f;
+ float range_begin_margin = 0.0f;
+ float range_end_margin = 0.0f;
+ };
+
+ class VisibilityArray : public BinSortedArray<InstanceVisibilityData> {
+ _FORCE_INLINE_ virtual void _update_idx(InstanceVisibilityData &r_element, uint64_t p_idx) {
+ r_element.instance->visibility_index = p_idx;
+ if (r_element.instance->scenario && r_element.instance->array_index != -1) {
+ r_element.instance->scenario->instance_data[r_element.instance->array_index].visibility_index = p_idx;
+ }
+ }
};
PagedArrayPool<InstanceBounds> instance_aabb_page_pool;
PagedArrayPool<InstanceData> instance_data_page_pool;
+ PagedArrayPool<InstanceVisibilityData> instance_visibility_data_page_pool;
struct Scenario {
enum IndexerType {
@@ -283,7 +315,6 @@ public:
DynamicBVH indexers[INDEXER_MAX];
- RS::ScenarioDebugMode debug;
RID self;
List<Instance *> directional_lights;
@@ -292,6 +323,8 @@ public:
RID camera_effects;
RID reflection_probe_shadow_atlas;
RID reflection_atlas;
+ uint64_t used_viewport_visibility_bits;
+ Map<RID, uint64_t> viewport_visibility_masks;
SelfList<Instance>::List instances;
@@ -299,17 +332,18 @@ public:
PagedArray<InstanceBounds> instance_aabbs;
PagedArray<InstanceData> instance_data;
+ VisibilityArray instance_visibility;
Scenario() {
indexers[INDEXER_GEOMETRY].set_index(INDEXER_GEOMETRY);
indexers[INDEXER_VOLUMES].set_index(INDEXER_VOLUMES);
- debug = RS::SCENARIO_DEBUG_DISABLED;
+ used_viewport_visibility_bits = 0;
}
};
int indexer_update_iterations = 0;
- mutable RID_PtrOwner<Scenario, true> scenario_owner;
+ mutable RID_Owner<Scenario, true> scenario_owner;
static void _instance_pair(Instance *p_A, Instance *p_B);
static void _instance_unpair(Instance *p_A, Instance *p_B);
@@ -319,13 +353,14 @@ public:
virtual RID scenario_allocate();
virtual void scenario_initialize(RID p_rid);
- virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx);
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count);
virtual bool is_scenario(RID p_scenario) const;
virtual RID scenario_get_environment(RID p_scenario);
+ virtual void scenario_add_viewport_visibility_mask(RID p_scenario, RID p_viewport);
+ virtual void scenario_remove_viewport_visibility_mask(RID p_scenario, RID p_viewport);
/* INSTANCING API */
@@ -399,6 +434,12 @@ public:
//scenario stuff
DynamicBVH::ID indexer_id;
int32_t array_index;
+ int32_t visibility_index = -1;
+ float visibility_range_begin;
+ float visibility_range_end;
+ float visibility_range_begin_margin;
+ float visibility_range_end_margin;
+ Instance *visibility_parent = nullptr;
Scenario *scenario;
SelfList<Instance> scenario_item;
@@ -412,12 +453,6 @@ public:
float extra_margin;
ObjectID object_id;
- float lod_begin;
- float lod_end;
- float lod_begin_hysteresis;
- float lod_end_hysteresis;
- RID lod_instance;
-
Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior
uint64_t last_frame_pass;
@@ -495,10 +530,10 @@ public:
visible = true;
- lod_begin = 0;
- lod_end = 0;
- lod_begin_hysteresis = 0;
- lod_end_hysteresis = 0;
+ visibility_range_begin = 0;
+ visibility_range_end = 0;
+ visibility_range_begin_margin = 0;
+ visibility_range_end_margin = 0;
last_frame_pass = 0;
version = 1;
@@ -537,6 +572,8 @@ public:
Set<Instance *> reflection_probes;
Set<Instance *> voxel_gi_instances;
Set<Instance *> lightmap_captures;
+ Set<Instance *> visibility_dependencies;
+ uint32_t visibility_dependencies_depth = 0;
InstanceGeometryData() {
can_cast_shadows = true;
@@ -576,6 +613,18 @@ public:
RID instance;
};
+ struct InstanceVisibilityNotifierData : public InstanceBaseData {
+ bool just_visible = false;
+ uint64_t visible_in_frame = 0;
+ RID base;
+ SelfList<InstanceVisibilityNotifierData> list_element;
+ InstanceVisibilityNotifierData() :
+ list_element(this) {}
+ };
+
+ SpinLock visible_notifier_list_lock;
+ SelfList<InstanceVisibilityNotifierData>::List visible_notifier_list;
+
struct InstanceLightData : public InstanceBaseData {
RID instance;
uint64_t last_version;
@@ -717,7 +766,7 @@ public:
PagedArray<Instance *> instance_cull_result;
PagedArray<Instance *> instance_shadow_cull_result;
- struct FrustumCullResult {
+ struct InstanceCullResult {
PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances;
PagedArray<Instance *> lights;
PagedArray<RID> light_instances;
@@ -782,7 +831,7 @@ public:
}
}
- void append_from(FrustumCullResult &p_cull_result) {
+ void append_from(InstanceCullResult &p_cull_result) {
geometry_instances.merge_unordered(p_cull_result.geometry_instances);
lights.merge_unordered(p_cull_result.lights);
light_instances.merge_unordered(p_cull_result.light_instances);
@@ -832,8 +881,8 @@ public:
}
};
- FrustumCullResult frustum_cull_result;
- LocalVector<FrustumCullResult> frustum_cull_result_threads;
+ InstanceCullResult scene_cull_result;
+ LocalVector<InstanceCullResult> scene_cull_result_threads;
RendererSceneRender::RenderShadowData render_shadow_data[MAX_UPDATE_SHADOWS];
uint32_t max_shadows_used = 0;
@@ -843,7 +892,7 @@ public:
uint32_t thread_cull_threshold = 200;
- RID_PtrOwner<Instance, true> instance_owner;
+ RID_Owner<Instance, true> instance_owner;
uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecessary on clustered
@@ -862,10 +911,14 @@ public:
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton);
- virtual void instance_set_exterior(RID p_instance, bool p_enabled);
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin);
+ virtual void instance_set_visibility_parent(RID p_instance, RID p_parent_instance);
+
+ void _update_instance_visibility_depth(Instance *p_instance);
+ void _update_instance_visibility_dependencies(Instance *p_instance);
+
// don't use these in a game!
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const;
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
@@ -875,8 +928,8 @@ public:
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting);
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
- virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
- virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
+ virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
+
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
@@ -937,6 +990,19 @@ public:
Frustum frustum;
} cull;
+ struct VisibilityCullData {
+ uint64_t viewport_mask;
+ Scenario *scenario;
+ Vector3 camera_position;
+ uint32_t cull_offset;
+ uint32_t cull_count;
+ };
+
+ void _visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data);
+ void _visibility_cull(const VisibilityCullData &cull_data, uint64_t p_from, uint64_t p_to);
+ _FORCE_INLINE_ void _visibility_cull(const VisibilityCullData &cull_data, uint64_t p_idx);
+ _FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask);
+
struct CullData {
Cull *cull;
Scenario *scenario;
@@ -946,17 +1012,17 @@ public:
Instance *render_reflection_probe;
const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer;
const CameraMatrix *camera_matrix;
+ uint64_t visibility_viewport_mask;
};
- void _frustum_cull_threaded(uint32_t p_thread, CullData *cull_data);
- void _frustum_cull(CullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to);
+ void _scene_cull_threaded(uint32_t p_thread, CullData *cull_data);
+ void _scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
- void _render_scene(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true);
+ void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, bool p_using_shadows = true);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
- void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas);
- void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas);
+ void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface);
void update_dirty_instances();
void render_particle_colliders();
@@ -1054,7 +1120,7 @@ public:
/* Render Buffers */
PASS0R(RID, render_buffers_create)
- PASS7(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool)
+ PASS8(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, uint32_t)
PASS1(gi_set_use_half_resolution, bool)
/* Shadow Atlas */
@@ -1070,6 +1136,8 @@ public:
void set_scene_render(RendererSceneRender *p_scene_render);
+ virtual void update_visibility_notifiers();
+
RendererSceneCull();
virtual ~RendererSceneCull();
};
diff --git a/servers/rendering/renderer_scene_occlusion_cull.cpp b/servers/rendering/renderer_scene_occlusion_cull.cpp
index c491ccbe7a..1b8aea36d7 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.cpp
+++ b/servers/rendering/renderer_scene_occlusion_cull.cpp
@@ -172,7 +172,7 @@ RID RendererSceneOcclusionCull::HZBuffer::get_debug_texture() {
}
if (debug_image.is_null()) {
- debug_image.instance();
+ debug_image.instantiate();
}
unsigned char *ptrw = debug_data.ptrw();
@@ -185,7 +185,7 @@ RID RendererSceneOcclusionCull::HZBuffer::get_debug_texture() {
if (debug_texture.is_null()) {
debug_texture = RS::get_singleton()->texture_2d_create(debug_image);
} else {
- RenderingServer::get_singleton()->texture_2d_update_immediate(debug_texture, debug_image);
+ RenderingServer::get_singleton()->texture_2d_update(debug_texture, debug_image);
}
return debug_texture;
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index f27bdc6798..3a230ac89d 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -29,3 +29,153 @@
/*************************************************************************/
#include "renderer_scene_render.h"
+
+void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect) {
+ view_count = 1;
+ is_ortogonal = p_is_ortogonal;
+ vaspect = p_vaspect;
+
+ main_transform = p_transform;
+ main_projection = p_projection;
+
+ view_offset[0] = Transform3D();
+ view_projection[0] = p_projection;
+}
+
+void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect) {
+ ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view");
+
+ view_count = p_view_count;
+ is_ortogonal = p_is_ortogonal;
+ vaspect = p_vaspect;
+ Vector<Plane> planes[2];
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Figure out our center transform
+
+ // 1. obtain our planes
+ for (uint32_t v = 0; v < view_count; v++) {
+ planes[v] = p_projections[v].get_projection_planes(p_transforms[v]);
+ }
+
+ // 2. average and normalize plane normals to obtain z vector, cross them to obtain y vector, and from there the x vector for combined camera basis.
+ Vector3 n0 = planes[0][CameraMatrix::PLANE_LEFT].normal;
+ Vector3 n1 = planes[1][CameraMatrix::PLANE_RIGHT].normal;
+ Vector3 z = (n0 + n1).normalized();
+ Vector3 y = n0.cross(n1).normalized();
+ Vector3 x = y.cross(z).normalized();
+ y = z.cross(x).normalized();
+ main_transform.basis.set(x, y, z);
+
+ // 3. create a horizon plane with one of the eyes and the up vector as normal.
+ Plane horizon(p_transforms[0].origin, y);
+
+ // 4. Intersect horizon, left and right to obtain the combined camera origin.
+ ERR_FAIL_COND_MSG(
+ !horizon.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin");
+
+ // handy to have the inverse of the transform we just build
+ Transform3D main_transform_inv = main_transform.inverse();
+
+ // 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
+ Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5;
+ Plane far(far_center, -z);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Figure out our top/bottom planes
+
+ // 6. Intersect far and left planes with top planes from both eyes, save the point with highest y as top_left.
+ Vector3 top_left, other;
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector");
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/left/top vector");
+ if (y.dot(top_left) < y.dot(other)) {
+ top_left = other;
+ }
+
+ // 7. Intersect far and left planes with bottom planes from both eyes, save the point with lowest y as bottom_left.
+ Vector3 bottom_left;
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector");
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector");
+ if (y.dot(other) < y.dot(bottom_left)) {
+ bottom_left = other;
+ }
+
+ // 8. Intersect far and right planes with top planes from both eyes, save the point with highest y as top_right.
+ Vector3 top_right;
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector");
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/right/top vector");
+ if (y.dot(top_right) < y.dot(other)) {
+ top_right = other;
+ }
+
+ // 9. Intersect far and right planes with bottom planes from both eyes, save the point with lowest y as bottom_right.
+ Vector3 bottom_right;
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector");
+ ERR_FAIL_COND_MSG(
+ !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector");
+ if (y.dot(other) < y.dot(bottom_right)) {
+ bottom_right = other;
+ }
+
+ // 10. Create top plane with these points: camera origin, top_left, top_right
+ Plane top(main_transform.origin, top_left, top_right);
+
+ // 11. Create bottom plane with these points: camera origin, bottom_left, bottom_right
+ Plane bottom(main_transform.origin, bottom_left, bottom_right);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Figure out our near plane points
+
+ // 12. Create a near plane using -camera z and the eye further along in that axis.
+ Plane near;
+ Vector3 neg_z = -z;
+ if (neg_z.dot(p_transforms[1].origin) < neg_z.dot(p_transforms[0].origin)) {
+ near = Plane(p_transforms[0].origin, neg_z);
+ } else {
+ near = Plane(p_transforms[1].origin, neg_z);
+ }
+
+ // 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec
+ Vector3 min_vec;
+ ERR_FAIL_COND_MSG(
+ !near.intersect_3(bottom, planes[0][CameraMatrix::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector");
+ ERR_FAIL_COND_MSG(
+ !near.intersect_3(bottom, planes[1][CameraMatrix::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector");
+ if (x.dot(other) < x.dot(min_vec)) {
+ min_vec = other;
+ }
+
+ Vector3 max_vec;
+ ERR_FAIL_COND_MSG(
+ !near.intersect_3(top, planes[0][CameraMatrix::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector");
+ ERR_FAIL_COND_MSG(
+ !near.intersect_3(top, planes[1][CameraMatrix::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector");
+ if (x.dot(max_vec) < x.dot(other)) {
+ max_vec = other;
+ }
+
+ // 14. transform these points by the inverse camera to obtain local_min_vec and local_max_vec
+ Vector3 local_min_vec = main_transform_inv.xform(min_vec);
+ Vector3 local_max_vec = main_transform_inv.xform(max_vec);
+
+ // 15. get x and y from these to obtain left, top, right bottom for the frustum. Get the distance from near plane to camera origin to obtain near, and the distance from the far plane to the camer origin to obtain far.
+ float z_near = -near.distance_to(main_transform.origin);
+ float z_far = -far.distance_to(main_transform.origin);
+
+ // 16. Use this to build the combined camera matrix.
+ main_projection.set_frustum(local_min_vec.x, local_max_vec.x, local_min_vec.y, local_max_vec.y, z_near, z_far);
+
+ /////////////////////////////////////////////////////////////////////////////
+ // 3. Copy our view data
+ for (uint32_t v = 0; v < view_count; v++) {
+ view_offset[v] = main_transform_inv * p_transforms[v];
+ view_projection[v] = p_projections[v] * CameraMatrix(view_offset[v].inverse());
+ }
+}
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 5f3e6df4e3..3682122dd3 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -39,7 +39,8 @@ class RendererSceneRender {
public:
enum {
MAX_DIRECTIONAL_LIGHTS = 8,
- MAX_DIRECTIONAL_LIGHT_CASCADES = 4
+ MAX_DIRECTIONAL_LIGHT_CASCADES = 4,
+ MAX_RENDER_VIEWS = 2
};
struct GeometryInstance {
@@ -216,7 +217,24 @@ public:
uint32_t positional_light_count;
};
- virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) = 0;
+ struct CameraData {
+ // flags
+ uint32_t view_count;
+ bool is_ortogonal;
+ bool vaspect;
+
+ // Main/center projection
+ Transform3D main_transform;
+ CameraMatrix main_projection;
+
+ Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS];
+ CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+
+ void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_ortogonal, bool p_vaspect);
+ void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_ortogonal, bool p_vaspect);
+ };
+
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr) = 0;
virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
@@ -226,7 +244,7 @@ public:
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
+ virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index 0b9b82cba0..c491e05be5 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -130,7 +130,6 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
- virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
@@ -230,7 +229,9 @@ public:
virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0;
virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
- virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
@@ -288,24 +289,6 @@ public:
virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
- /* IMMEDIATE API */
-
- virtual RID immediate_allocate() = 0;
- virtual void immediate_initialize(RID p_rid) = 0;
-
- virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0;
- virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0;
- virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0;
- virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0;
- virtual void immediate_color(RID p_immediate, const Color &p_color) = 0;
- virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0;
- virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0;
- virtual void immediate_end(RID p_immediate) = 0;
- virtual void immediate_clear(RID p_immediate) = 0;
- virtual void immediate_set_material(RID p_immediate, RID p_material) = 0;
- virtual RID immediate_get_material(RID p_immediate) const = 0;
- virtual AABB immediate_get_aabb(RID p_immediate) const = 0;
-
/* SKELETON API */
virtual RID skeleton_allocate() = 0;
@@ -348,8 +331,6 @@ public:
virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0;
virtual bool light_directional_is_sky_only(RID p_light) const = 0;
- virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0;
- virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0;
virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
@@ -438,12 +419,6 @@ public:
virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0;
- virtual void voxel_gi_set_ao(RID p_voxel_gi, float p_ao) = 0;
- virtual float voxel_gi_get_ao(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_ao_size(RID p_voxel_gi, float p_strength) = 0;
- virtual float voxel_gi_get_ao_size(RID p_voxel_gi) const = 0;
-
virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0;
@@ -557,6 +532,14 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
+ virtual RID visibility_notifier_allocate() = 0;
+ virtual void visibility_notifier_initialize(RID p_notifier) = 0;
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
+
//used from 2D and 3D
virtual RID particles_collision_instance_create(RID p_collision) = 0;
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
@@ -590,7 +573,7 @@ public:
virtual RID render_target_create() = 0;
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
- virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
virtual RID render_target_get_texture(RID p_render_target) = 0;
virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index f97e24947d..b3301fc607 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -71,11 +71,11 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
return xf;
}
-void RendererViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye) {
+void RendererViewport::_draw_3d(Viewport *p_viewport) {
RENDER_TIMESTAMP(">Begin Rendering 3D Scene");
Ref<XRInterface> xr_interface;
- if (XRServer::get_singleton() != nullptr) {
+ if (p_viewport->use_xr && XRServer::get_singleton() != nullptr) {
xr_interface = XRServer::get_singleton()->get_primary_interface();
}
@@ -95,15 +95,12 @@ void RendererViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye) {
}
float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width);
- if (p_viewport->use_xr && xr_interface.is_valid()) {
- RSG::scene->render_camera(p_viewport->render_buffers, xr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas);
- } else {
- RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas);
- }
+ RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->self, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas, xr_interface);
+
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
-void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye) {
+void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_count) {
if (p_viewport->measure_render_time) {
String rt_id = "vp_begin_" + itos(p_viewport->self.get_id());
RSG::storage->capture_timestamp(rt_id);
@@ -117,7 +114,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
Color bgcolor = RSG::storage->get_default_clear_color();
- if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) {
+ if (!p_viewport->disable_2d && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) {
RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario);
if (RSG::scene->is_environment(environment)) {
scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS;
@@ -125,7 +122,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
}
}
- bool can_draw_3d = RSG::scene->is_camera(p_viewport->camera);
+ bool can_draw_3d = RSG::scene->is_camera(p_viewport->camera) && !p_viewport->disable_3d;
if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
if (p_viewport->transparent_bg) {
@@ -139,16 +136,16 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
//wants to draw 3D but there is no render buffer, create
p_viewport->render_buffers = RSG::scene->render_buffers_create();
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding);
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_view_count);
}
RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
if (!scenario_draw_canvas_bg && can_draw_3d) {
- _draw_3d(p_viewport, p_eye);
+ _draw_3d(p_viewport);
}
- if (!p_viewport->hide_canvas) {
+ if (!p_viewport->disable_2d) {
int i = 0;
Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
@@ -392,7 +389,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
- _draw_3d(p_viewport, p_eye);
+ _draw_3d(p_viewport);
}
scenario_draw_canvas_bg = false;
}
@@ -433,7 +430,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
- _draw_3d(p_viewport, p_eye);
+ _draw_3d(p_viewport);
}
scenario_draw_canvas_bg = false;
@@ -444,7 +441,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_
if (!can_draw_3d) {
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
} else {
- _draw_3d(p_viewport, p_eye);
+ _draw_3d(p_viewport);
}
}
}
@@ -481,7 +478,7 @@ void RendererViewport::draw_viewports() {
//sort viewports
active_viewports.sort_custom<ViewportSort>();
- Map<DisplayServer::WindowID, Vector<RendererCompositor::BlitToScreen>> blit_to_screen_list;
+ Map<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;
//draw viewports
RENDER_TIMESTAMP(">Render Viewports");
@@ -535,52 +532,54 @@ void RendererViewport::draw_viewports() {
RENDER_TIMESTAMP(">Rendering Viewport " + itos(i));
RSG::storage->render_target_set_as_unused(vp->render_target);
-#if 0
- // TODO fix up this code after we change our commit_for_eye to accept our new render targets
-
if (vp->use_xr && xr_interface.is_valid()) {
- // override our size, make sure it matches our required size
+ // override our size, make sure it matches our required size and is created as a stereo target
vp->size = xr_interface->get_render_targetsize();
- RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y);
+ uint32_t view_count = xr_interface->get_view_count();
+ RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
- // render mono or left eye first
- XRInterface::Eyes leftOrMono = xr_interface->is_stereo() ? XRInterface::EYE_LEFT : XRInterface::EYE_MONO;
-
- // check for an external texture destination for our left eye/mono
- // TODO investigate how we're going to make external textures work
- RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
+ // check for an external texture destination (disabled for now, not yet supported)
+ // RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
+ RSG::storage->render_target_set_external_texture(vp->render_target, 0);
- // set our render target as current
- RSG::rasterizer->set_current_render_target(vp->render_target);
+ // render...
+ RSG::scene->set_debug_draw_mode(vp->debug_draw);
+ RSG::storage->render_info_begin_capture();
- // and draw left eye/mono
- _draw_viewport(vp, leftOrMono);
- xr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect);
+ // and draw viewport
+ _draw_viewport(vp, view_count);
- // render right eye
- if (leftOrMono == XRInterface::EYE_LEFT) {
- // check for an external texture destination for our right eye
- RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(XRInterface::EYE_RIGHT));
+ // measure
+ RSG::storage->render_info_end_capture();
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_OBJECTS_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_VERTICES_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_MATERIAL_CHANGES_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SHADER_CHANGES_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SURFACE_CHANGES_IN_FRAME);
+ vp->render_info[RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_DRAW_CALLS_IN_FRAME);
- // commit for eye may have changed the render target
- RSG::rasterizer->set_current_render_target(vp->render_target);
+ // commit our eyes
+ Vector<BlitToScreen> blits = xr_interface->commit_views(vp->render_target, vp->viewport_to_screen_rect);
+ if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) {
+ if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
+ blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
+ }
- _draw_viewport(vp, XRInterface::EYE_RIGHT);
- xr_interface->commit_for_eye(XRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect);
+ for (int b = 0; b < blits.size(); b++) {
+ blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
+ }
}
// and for our frame timing, mark when we've finished committing our eyes
XRServer::get_singleton()->_mark_commit();
} else {
-#endif
- {
RSG::storage->render_target_set_external_texture(vp->render_target, 0);
RSG::scene->set_debug_draw_mode(vp->debug_draw);
RSG::storage->render_info_begin_capture();
// render standard mono camera
- _draw_viewport(vp);
+ _draw_viewport(vp, 1);
RSG::storage->render_info_end_capture();
vp->render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_OBJECTS_IN_FRAME);
@@ -592,7 +591,7 @@ void RendererViewport::draw_viewports() {
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !RSG::rasterizer->is_low_end())) {
//copy to screen if set as such
- RendererCompositor::BlitToScreen blit;
+ BlitToScreen blit;
blit.render_target = vp->render_target;
if (vp->viewport_to_screen_rect != Rect2()) {
blit.rect = vp->viewport_to_screen_rect;
@@ -602,7 +601,7 @@ void RendererViewport::draw_viewports() {
}
if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
- blit_to_screen_list[vp->viewport_to_screen] = Vector<RendererCompositor::BlitToScreen>();
+ blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
}
blit_to_screen_list[vp->viewport_to_screen].push_back(blit);
@@ -621,7 +620,7 @@ void RendererViewport::draw_viewports() {
//this needs to be called to make screen swapping more efficient
RSG::rasterizer->prepare_for_blitting_render_targets();
- for (Map<int, Vector<RendererCompositor::BlitToScreen>>::Element *E = blit_to_screen_list.front(); E; E = E->next()) {
+ for (Map<int, Vector<BlitToScreen>>::Element *E = blit_to_screen_list.front(); E; E = E->next()) {
RSG::rasterizer->blit_render_targets_to_screen(E->key(), E->get().ptr(), E->get().size());
}
}
@@ -631,22 +630,41 @@ RID RendererViewport::viewport_allocate() {
}
void RendererViewport::viewport_initialize(RID p_rid) {
- Viewport *viewport = memnew(Viewport);
+ viewport_owner.initialize_rid(p_rid);
+ Viewport *viewport = viewport_owner.getornull(p_rid);
viewport->self = p_rid;
- viewport->hide_scenario = false;
- viewport->hide_canvas = false;
viewport->render_target = RSG::storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
-
- viewport_owner.initialize_rid(p_rid, viewport);
}
void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
+ if (viewport->use_xr == p_use_xr) {
+ return;
+ }
+
viewport->use_xr = p_use_xr;
+ if (viewport->render_buffers.is_valid()) {
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding, viewport->get_view_count());
+ }
+}
+
+uint32_t RendererViewport::Viewport::get_view_count() {
+ uint32_t view_count = 1;
+
+ if (use_xr && XRServer::get_singleton() != nullptr) {
+ Ref<XRInterface> xr_interface;
+
+ xr_interface = XRServer::get_singleton()->get_primary_interface();
+ if (xr_interface.is_valid()) {
+ view_count = xr_interface->get_view_count();
+ }
+ }
+
+ return view_count;
}
void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
@@ -656,13 +674,14 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
ERR_FAIL_COND(!viewport);
viewport->size = Size2(p_width, p_height);
- RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height);
+ uint32_t view_count = viewport->get_view_count();
+ RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
if (viewport->render_buffers.is_valid()) {
if (p_width == 0 || p_height == 0) {
RSG::scene->free(viewport->render_buffers);
viewport->render_buffers = RID();
} else {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding);
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding, view_count);
}
}
@@ -704,7 +723,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// If using GLES2 we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
- RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y);
+ RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
RSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
}
@@ -714,7 +733,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
+ RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
}
viewport->viewport_to_screen_rect = Rect2();
@@ -733,7 +752,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if disabled, reset render_target size and position
if (!p_enable) {
RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
+ RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
}
RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
@@ -741,7 +760,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
- RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y);
+ RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
RSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
}
}
@@ -770,25 +789,25 @@ RID RendererViewport::viewport_get_occluder_debug_texture(RID p_viewport) const
return RID();
}
-void RendererViewport::viewport_set_hide_scenario(RID p_viewport, bool p_hide) {
+void RendererViewport::viewport_set_disable_2d(RID p_viewport, bool p_disable) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->hide_scenario = p_hide;
+ viewport->disable_2d = p_disable;
}
-void RendererViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) {
+void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->hide_canvas = p_hide;
+ viewport->disable_environment = p_disable;
}
-void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
+void RendererViewport::viewport_set_disable_3d(RID p_viewport, bool p_disable) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->disable_environment = p_disable;
+ viewport->disable_3d = p_disable;
}
void RendererViewport::viewport_attach_camera(RID p_viewport, RID p_camera) {
@@ -802,6 +821,10 @@ void RendererViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
+ if (viewport->scenario.is_valid()) {
+ RSG::scene->scenario_remove_viewport_visibility_mask(viewport->scenario, p_viewport);
+ }
+
viewport->scenario = p_scenario;
if (viewport->use_occlusion_culling) {
RendererSceneOcclusionCull::get_singleton()->buffer_set_scenario(p_viewport, p_scenario);
@@ -892,7 +915,7 @@ void RendererViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa
}
viewport->msaa = p_msaa;
if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding);
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding, viewport->get_view_count());
}
}
@@ -905,7 +928,7 @@ void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::Viewport
}
viewport->screen_space_aa = p_mode;
if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding);
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding, viewport->get_view_count());
}
}
@@ -918,7 +941,7 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
}
viewport->use_debanding = p_use_debanding;
if (viewport->render_buffers.is_valid()) {
- RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding);
+ RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding, viewport->get_view_count());
}
}
@@ -1059,7 +1082,6 @@ bool RendererViewport::free(RID p_rid) {
}
viewport_owner.free(p_rid);
- memdelete(viewport);
return true;
}
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 5c372e8c9a..bf47bda148 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -68,9 +68,9 @@ public:
Rect2 viewport_to_screen_rect;
bool viewport_render_direct_to_screen;
- bool hide_scenario;
- bool hide_canvas;
- bool disable_environment;
+ bool disable_2d = false;
+ bool disable_environment = false;
+ bool disable_3d = false;
bool measure_render_time;
bool snap_2d_transforms_to_pixel;
@@ -137,7 +137,7 @@ public:
update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE;
clear_mode = RS::VIEWPORT_CLEAR_ALWAYS;
transparent_bg = false;
- disable_environment = false;
+
viewport_to_screen = DisplayServer::INVALID_WINDOW_ID;
shadow_atlas_size = 0;
measure_render_time = false;
@@ -164,13 +164,15 @@ public:
time_gpu_begin = 0;
time_gpu_end = 0;
}
+
+ uint32_t get_view_count();
};
HashMap<String, RID> timestamp_vp_map;
uint64_t draw_viewports_pass = 0;
- mutable RID_PtrOwner<Viewport, true> viewport_owner;
+ mutable RID_Owner<Viewport, true> viewport_owner;
struct ViewportSort {
_FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
@@ -187,8 +189,8 @@ public:
Vector<Viewport *> active_viewports;
private:
- void _draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye);
- void _draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye = XRInterface::EYE_MONO);
+ void _draw_3d(Viewport *p_viewport);
+ void _draw_viewport(Viewport *p_viewport, uint32_t p_view_count = 1);
int occlusion_rays_per_thread = 512;
@@ -215,9 +217,9 @@ public:
RID viewport_get_texture(RID p_viewport) const;
RID viewport_get_occluder_debug_texture(RID p_viewport) const;
- void viewport_set_hide_scenario(RID p_viewport, bool p_hide);
- void viewport_set_hide_canvas(RID p_viewport, bool p_hide);
+ void viewport_set_disable_2d(RID p_viewport, bool p_disable);
void viewport_set_disable_environment(RID p_viewport, bool p_disable);
+ void viewport_set_disable_3d(RID p_viewport, bool p_disable);
void viewport_attach_camera(RID p_viewport, RID p_camera);
void viewport_set_scenario(RID p_viewport, RID p_scenario);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 056cec4c1f..c52d97a3de 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -98,7 +98,7 @@ RID RenderingDevice::_texture_create_shared_from_slice(const Ref<RDTextureView>
return texture_create_shared_from_slice(p_view->base, p_with_texture, p_layer, p_mipmap, p_slice_type);
}
-RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments) {
+RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count) {
Vector<AttachmentFormat> attachments;
attachments.resize(p_attachments.size());
@@ -107,12 +107,43 @@ RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create
ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
attachments.write[i] = af->base;
}
- return framebuffer_format_create(attachments);
+ return framebuffer_format_create(attachments, p_view_count);
}
-RID RenderingDevice::_framebuffer_create(const Array &p_textures, FramebufferFormatID p_format_check) {
+RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create_multipass(const TypedArray<RDAttachmentFormat> &p_attachments, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_view_count) {
+ Vector<AttachmentFormat> attachments;
+ attachments.resize(p_attachments.size());
+
+ for (int i = 0; i < p_attachments.size(); i++) {
+ Ref<RDAttachmentFormat> af = p_attachments[i];
+ ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
+ attachments.write[i] = af->base;
+ }
+
+ Vector<FramebufferPass> passes;
+ for (int i = 0; i < p_passes.size(); i++) {
+ Ref<RDFramebufferPass> pass = p_passes[i];
+ ERR_CONTINUE(pass.is_null());
+ passes.push_back(pass->base);
+ }
+
+ return framebuffer_format_create_multipass(attachments, passes, p_view_count);
+}
+
+RID RenderingDevice::_framebuffer_create(const TypedArray<RID> &p_textures, FramebufferFormatID p_format_check, uint32_t p_view_count) {
Vector<RID> textures = Variant(p_textures);
- return framebuffer_create(textures, p_format_check);
+ return framebuffer_create(textures, p_format_check, p_view_count);
+}
+
+RID RenderingDevice::_framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) {
+ Vector<RID> textures = Variant(p_textures);
+ Vector<FramebufferPass> passes;
+ for (int i = 0; i < p_passes.size(); i++) {
+ Ref<RDFramebufferPass> pass = p_passes[i];
+ ERR_CONTINUE(pass.is_null());
+ passes.push_back(pass->base);
+ }
+ return framebuffer_create_multipass(textures, passes, p_format_check, p_view_count);
}
RID RenderingDevice::_sampler_create(const Ref<RDSamplerState> &p_state) {
@@ -143,7 +174,7 @@ Ref<RDShaderBytecode> RenderingDevice::_shader_compile_from_source(const Ref<RDS
ERR_FAIL_COND_V(p_source.is_null(), Ref<RDShaderBytecode>());
Ref<RDShaderBytecode> bytecode;
- bytecode.instance();
+ bytecode.instantiate();
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String error;
@@ -190,7 +221,7 @@ Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t
return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_post_barrier);
}
-RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags) {
+RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass) {
PipelineRasterizationState rasterization_state;
if (p_rasterization_state.is_valid()) {
rasterization_state = p_rasterization_state->base;
@@ -221,7 +252,7 @@ RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p
}
}
- return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags);
+ return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags, p_for_render_pass);
}
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) {
@@ -242,6 +273,22 @@ Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint3
return split_ids;
}
+Vector<int64_t> RenderingDevice::_draw_list_switch_to_next_pass_split(uint32_t p_splits) {
+ Vector<DrawListID> splits;
+ splits.resize(p_splits);
+
+ Error err = draw_list_switch_to_next_pass_split(p_splits, splits.ptrw());
+ ERR_FAIL_COND_V(err != OK, Vector<int64_t>());
+
+ Vector<int64_t> split_ids;
+ split_ids.resize(splits.size());
+ for (int i = 0; i < splits.size(); i++) {
+ split_ids.write[i] = splits[i];
+ }
+
+ return split_ids;
+}
+
void RenderingDevice::_draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size) {
ERR_FAIL_COND((uint32_t)p_data.size() > p_data_size);
draw_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
@@ -269,10 +316,12 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::texture_clear, DEFVAL(BARRIER_MASK_ALL));
ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::texture_resolve_multisample, DEFVAL(BARRIER_MASK_ALL));
- ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments"), &RenderingDevice::_framebuffer_format_create);
+ ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments", "view_count"), &RenderingDevice::_framebuffer_format_create, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("framebuffer_format_create_multipass", "attachments", "passes", "view_count"), &RenderingDevice::_framebuffer_format_create_multipass, DEFVAL(1));
ClassDB::bind_method(D_METHOD("framebuffer_format_create_empty", "samples"), &RenderingDevice::framebuffer_format_create_empty, DEFVAL(TEXTURE_SAMPLES_1));
- ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format"), &RenderingDevice::framebuffer_format_get_texture_samples);
- ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID));
+ ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format", "render_pass"), &RenderingDevice::framebuffer_format_get_texture_samples, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("framebuffer_create_multipass", "textures", "passes", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create_multipass, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "samples", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(TEXTURE_SAMPLES_1), DEFVAL(INVALID_FORMAT_ID));
ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
@@ -299,7 +348,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL));
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
- ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags"), &RenderingDevice::_render_pipeline_create, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0));
ClassDB::bind_method(D_METHOD("render_pipeline_is_valid", "render_pipeline"), &RenderingDevice::render_pipeline_is_valid);
ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader"), &RenderingDevice::compute_pipeline_create);
@@ -325,6 +374,9 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2i()));
ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor);
+ ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass"), &RenderingDevice::draw_list_switch_to_next_pass);
+ ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass_split", "splits"), &RenderingDevice::_draw_list_switch_to_next_pass_split);
+
ClassDB::bind_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::draw_list_end, DEFVAL(BARRIER_MASK_ALL));
ClassDB::bind_method(D_METHOD("compute_list_begin", "allow_draw_overlap"), &RenderingDevice::compute_list_begin, DEFVAL(false));
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 4dcb9b963e..be7e127491 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -47,6 +47,7 @@ class RDPipelineRasterizationState;
class RDPipelineMultisampleState;
class RDPipelineDepthStencilState;
class RDPipelineColorBlendState;
+class RDFramebufferPass;
class RenderingDevice : public Object {
GDCLASS(RenderingDevice, Object)
@@ -516,11 +517,24 @@ public:
typedef int64_t FramebufferFormatID;
// This ID is warranted to be unique for the same formats, does not need to be freed
- virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format) = 0;
+ virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1) = 0;
+ struct FramebufferPass {
+ enum {
+ ATTACHMENT_UNUSED = -1
+ };
+ Vector<int32_t> color_attachments;
+ Vector<int32_t> input_attachments;
+ Vector<int32_t> resolve_attachments;
+ Vector<int32_t> preserve_attachments;
+ int32_t depth_attachment = ATTACHMENT_UNUSED;
+ };
+
+ virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1) = 0;
- virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0;
+ virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0) = 0;
- virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0;
+ virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
+ virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID) = 0;
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0;
@@ -962,7 +976,7 @@ public:
};
virtual bool render_pipeline_is_valid(RID p_pipeline) = 0;
- virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0) = 0;
+ virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0) = 0;
/**************************/
/**** COMPUTE PIPELINE ****/
@@ -1018,6 +1032,9 @@ public:
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) = 0;
virtual void draw_list_disable_scissor(DrawListID p_list) = 0;
+ virtual DrawListID draw_list_switch_to_next_pass() = 0;
+ virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) = 0;
+
virtual void draw_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
/***********************/
@@ -1134,8 +1151,10 @@ protected:
RID _texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture);
RID _texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
- FramebufferFormatID _framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments);
- RID _framebuffer_create(const Array &p_textures, FramebufferFormatID p_format_check = INVALID_ID);
+ FramebufferFormatID _framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count);
+ FramebufferFormatID _framebuffer_format_create_multipass(const TypedArray<RDAttachmentFormat> &p_attachments, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_view_count);
+ RID _framebuffer_create(const TypedArray<RID> &p_textures, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
+ RID _framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
RID _sampler_create(const Ref<RDSamplerState> &p_state);
VertexFormatID _vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats);
RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers);
@@ -1146,11 +1165,12 @@ protected:
Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
- RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0);
+ RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0);
Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>());
void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
+ Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits);
};
VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index 2f11360364..2652edb1bc 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -156,7 +156,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
}
Ref<RDShaderFile> shader_file;
- shader_file.instance();
+ shader_file.instantiate();
if (base_error == "") {
if (stage_found[RD::SHADER_STAGE_COMPUTE] && stages_found > 1) {
@@ -173,7 +173,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
for (Map<StringName, String>::Element *E = version_texts.front(); E; E = E->next()) {
Ref<RDShaderBytecode> bytecode;
- bytecode.instance();
+ bytecode.instantiate();
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String code = stage_code[i];
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index e43c3669b5..dc59568ce9 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -51,8 +51,8 @@
ClassDB::bind_method(D_METHOD("get_" _MKSTR(m_sub) "_" _MKSTR(m_member)), &m_class::get_##m_sub##_##m_member); \
ADD_PROPERTY(PropertyInfo(m_variant_type, _MKSTR(m_sub) "_" _MKSTR(m_member)), "set_" _MKSTR(m_sub) "_" _MKSTR(m_member), "get_" _MKSTR(m_sub) "_" _MKSTR(m_member))
-class RDTextureFormat : public Reference {
- GDCLASS(RDTextureFormat, Reference)
+class RDTextureFormat : public RefCounted {
+ GDCLASS(RDTextureFormat, RefCounted)
friend class RenderingDevice;
RD::TextureFormat base;
@@ -87,8 +87,8 @@ protected:
}
};
-class RDTextureView : public Reference {
- GDCLASS(RDTextureView, Reference)
+class RDTextureView : public RefCounted {
+ GDCLASS(RDTextureView, RefCounted)
friend class RenderingDevice;
@@ -110,8 +110,8 @@ protected:
}
};
-class RDAttachmentFormat : public Reference {
- GDCLASS(RDAttachmentFormat, Reference)
+class RDAttachmentFormat : public RefCounted {
+ GDCLASS(RDAttachmentFormat, RefCounted)
friend class RenderingDevice;
RD::AttachmentFormat base;
@@ -128,8 +128,36 @@ protected:
}
};
-class RDSamplerState : public Reference {
- GDCLASS(RDSamplerState, Reference)
+class RDFramebufferPass : public RefCounted {
+ GDCLASS(RDFramebufferPass, RefCounted)
+ friend class RenderingDevice;
+
+ RD::FramebufferPass base;
+
+public:
+ RD_SETGET(PackedInt32Array, color_attachments)
+ RD_SETGET(PackedInt32Array, input_attachments)
+ RD_SETGET(PackedInt32Array, resolve_attachments)
+ RD_SETGET(PackedInt32Array, preserve_attachments)
+ RD_SETGET(int32_t, depth_attachment)
+protected:
+ enum {
+ ATTACHMENT_UNUSED = -1
+ };
+
+ static void _bind_methods() {
+ RD_BIND(Variant::PACKED_INT32_ARRAY, RDFramebufferPass, color_attachments);
+ RD_BIND(Variant::PACKED_INT32_ARRAY, RDFramebufferPass, input_attachments);
+ RD_BIND(Variant::PACKED_INT32_ARRAY, RDFramebufferPass, resolve_attachments);
+ RD_BIND(Variant::PACKED_INT32_ARRAY, RDFramebufferPass, preserve_attachments);
+ RD_BIND(Variant::INT, RDFramebufferPass, depth_attachment);
+
+ BIND_CONSTANT(ATTACHMENT_UNUSED);
+ }
+};
+
+class RDSamplerState : public RefCounted {
+ GDCLASS(RDSamplerState, RefCounted)
friend class RenderingDevice;
RD::SamplerState base;
@@ -171,8 +199,8 @@ protected:
}
};
-class RDVertexAttribute : public Reference {
- GDCLASS(RDVertexAttribute, Reference)
+class RDVertexAttribute : public RefCounted {
+ GDCLASS(RDVertexAttribute, RefCounted)
friend class RenderingDevice;
RD::VertexAttribute base;
@@ -192,8 +220,8 @@ protected:
RD_BIND(Variant::INT, RDVertexAttribute, frequency);
}
};
-class RDShaderSource : public Reference {
- GDCLASS(RDShaderSource, Reference)
+class RDShaderSource : public RefCounted {
+ GDCLASS(RDShaderSource, RefCounted)
String source[RD::SHADER_STAGE_MAX];
RD::ShaderLanguage language = RD::SHADER_LANGUAGE_GLSL;
@@ -386,8 +414,8 @@ protected:
}
};
-class RDUniform : public Reference {
- GDCLASS(RDUniform, Reference)
+class RDUniform : public RefCounted {
+ GDCLASS(RDUniform, RefCounted)
friend class RenderingDevice;
RD::Uniform base;
@@ -424,8 +452,8 @@ protected:
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_ids", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_ids", "get_ids");
}
};
-class RDPipelineRasterizationState : public Reference {
- GDCLASS(RDPipelineRasterizationState, Reference)
+class RDPipelineRasterizationState : public RefCounted {
+ GDCLASS(RDPipelineRasterizationState, RefCounted)
friend class RenderingDevice;
RD::PipelineRasterizationState base;
@@ -459,8 +487,8 @@ protected:
}
};
-class RDPipelineMultisampleState : public Reference {
- GDCLASS(RDPipelineMultisampleState, Reference)
+class RDPipelineMultisampleState : public RefCounted {
+ GDCLASS(RDPipelineMultisampleState, RefCounted)
friend class RenderingDevice;
RD::PipelineMultisampleState base;
@@ -490,8 +518,8 @@ protected:
}
};
-class RDPipelineDepthStencilState : public Reference {
- GDCLASS(RDPipelineDepthStencilState, Reference)
+class RDPipelineDepthStencilState : public RefCounted {
+ GDCLASS(RDPipelineDepthStencilState, RefCounted)
friend class RenderingDevice;
RD::PipelineDepthStencilState base;
@@ -549,8 +577,8 @@ protected:
}
};
-class RDPipelineColorBlendStateAttachment : public Reference {
- GDCLASS(RDPipelineColorBlendStateAttachment, Reference)
+class RDPipelineColorBlendStateAttachment : public RefCounted {
+ GDCLASS(RDPipelineColorBlendStateAttachment, RefCounted)
friend class RenderingDevice;
RD::PipelineColorBlendState::Attachment base;
@@ -594,8 +622,8 @@ protected:
}
};
-class RDPipelineColorBlendState : public Reference {
- GDCLASS(RDPipelineColorBlendState, Reference)
+class RDPipelineColorBlendState : public RefCounted {
+ GDCLASS(RDPipelineColorBlendState, RefCounted)
friend class RenderingDevice;
RD::PipelineColorBlendState base;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index c6fe6a07e0..aad6163a16 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -42,26 +42,6 @@
int RenderingServerDefault::changes = 0;
-/* BLACK BARS */
-
-void RenderingServerDefault::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) {
- black_margin[SIDE_LEFT] = p_left;
- black_margin[SIDE_TOP] = p_top;
- black_margin[SIDE_RIGHT] = p_right;
- black_margin[SIDE_BOTTOM] = p_bottom;
-}
-
-void RenderingServerDefault::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) {
- black_image[SIDE_LEFT] = p_left;
- black_image[SIDE_TOP] = p_top;
- black_image[SIDE_RIGHT] = p_right;
- black_image[SIDE_BOTTOM] = p_bottom;
-}
-
-void RenderingServerDefault::_draw_margins() {
- RSG::canvas_render->draw_window_margins(black_margin, black_image);
-};
-
/* FREE */
void RenderingServerDefault::_free(RID p_rid) {
@@ -114,9 +94,11 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::viewport->draw_viewports();
RSG::canvas_render->update();
- _draw_margins();
RSG::rasterizer->end_frame(p_swap_buffers);
+ RSG::canvas->update_visibility_notifiers();
+ RSG::scene->update_visibility_notifiers();
+
while (frame_drawn_callbacks.front()) {
Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
if (obj) {
@@ -358,7 +340,7 @@ void RenderingServerDefault::_thread_loop() {
draw_thread_up.set();
while (!exit.is_set()) {
// flush commands one by one, until exit is requested
- command_queue.wait_and_flush_one();
+ command_queue.wait_and_flush();
}
command_queue.flush_all(); // flush all
@@ -396,6 +378,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
server_thread = 0;
}
+ RSG::threaded = p_create_thread;
RSG::canvas = memnew(RendererCanvasCull);
RSG::viewport = memnew(RendererViewport);
RendererSceneCull *sr = memnew(RendererSceneCull);
@@ -406,11 +389,6 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
sr->set_scene_render(RSG::rasterizer->get_scene());
frame_profile_frame = 0;
-
- for (int i = 0; i < 4; i++) {
- black_margin[i] = 0;
- black_image[i] = RID();
- }
}
RenderingServerDefault::~RenderingServerDefault() {
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 6476d7c75d..70bba91bab 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -58,9 +58,6 @@ class RenderingServerDefault : public RenderingServer {
static int changes;
RID test_cube;
- int black_margin[4];
- RID black_image[4];
-
struct FrameDrawnCallbacks {
ObjectID object;
StringName method;
@@ -69,7 +66,6 @@ class RenderingServerDefault : public RenderingServer {
List<FrameDrawnCallbacks> frame_drawn_callbacks;
- void _draw_margins();
static void _changes_changed() {}
uint64_t frame_profile_frame;
@@ -192,8 +188,6 @@ public:
FUNCRIDTEX6(texture_3d, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
FUNCRIDTEX1(texture_proxy, RID)
- //goes pass-through
- FUNC3(texture_2d_update_immediate, RID, const Ref<Image> &, int)
//these go through command queue if they are in another thread
FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &)
@@ -290,7 +284,9 @@ public:
FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
- FUNC4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
+ FUNC4(mesh_surface_update_vertex_region, RID, int, int, const Vector<uint8_t> &)
+ FUNC4(mesh_surface_update_attribute_region, RID, int, int, const Vector<uint8_t> &)
+ FUNC4(mesh_surface_update_skin_region, RID, int, int, const Vector<uint8_t> &)
FUNC3(mesh_surface_set_material, RID, int, RID)
FUNC2RC(RID, mesh_surface_get_material, RID, int)
@@ -333,21 +329,6 @@ public:
FUNC2(multimesh_set_visible_instances, RID, int)
FUNC1RC(int, multimesh_get_visible_instances, RID)
- /* IMMEDIATE API */
-
- FUNCRIDSPLIT(immediate)
- FUNC3(immediate_begin, RID, PrimitiveType, RID)
- FUNC2(immediate_vertex, RID, const Vector3 &)
- FUNC2(immediate_normal, RID, const Vector3 &)
- FUNC2(immediate_tangent, RID, const Plane &)
- FUNC2(immediate_color, RID, const Color &)
- FUNC2(immediate_uv, RID, const Vector2 &)
- FUNC2(immediate_uv2, RID, const Vector2 &)
- FUNC1(immediate_end, RID)
- FUNC1(immediate_clear, RID)
- FUNC2(immediate_set_material, RID, RID)
- FUNC1RC(RID, immediate_get_material, RID)
-
/* SKELETON API */
FUNCRIDSPLIT(skeleton)
@@ -381,7 +362,6 @@ public:
FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
FUNC2(light_directional_set_blend_splits, RID, bool)
FUNC2(light_directional_set_sky_only, RID, bool)
- FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
/* PROBE API */
@@ -431,34 +411,12 @@ public:
FUNC1RC(Transform3D, voxel_gi_get_to_cell_xform, RID)
FUNC2(voxel_gi_set_dynamic_range, RID, float)
- FUNC1RC(float, voxel_gi_get_dynamic_range, RID)
-
FUNC2(voxel_gi_set_propagation, RID, float)
- FUNC1RC(float, voxel_gi_get_propagation, RID)
-
FUNC2(voxel_gi_set_energy, RID, float)
- FUNC1RC(float, voxel_gi_get_energy, RID)
-
- FUNC2(voxel_gi_set_ao, RID, float)
- FUNC1RC(float, voxel_gi_get_ao, RID)
-
- FUNC2(voxel_gi_set_ao_size, RID, float)
- FUNC1RC(float, voxel_gi_get_ao_size, RID)
-
FUNC2(voxel_gi_set_bias, RID, float)
- FUNC1RC(float, voxel_gi_get_bias, RID)
-
FUNC2(voxel_gi_set_normal_bias, RID, float)
- FUNC1RC(float, voxel_gi_get_normal_bias, RID)
-
FUNC2(voxel_gi_set_interior, RID, bool)
- FUNC1RC(bool, voxel_gi_is_interior, RID)
-
FUNC2(voxel_gi_set_use_two_bounces, RID, bool)
- FUNC1RC(bool, voxel_gi_is_using_two_bounces, RID)
-
- FUNC2(voxel_gi_set_anisotropy_strength, RID, float)
- FUNC1RC(float, voxel_gi_get_anisotropy_strength, RID)
/* LIGHTMAP */
@@ -529,6 +487,12 @@ public:
FUNC1(particles_collision_height_field_update, RID)
FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
+ /* VISIBILITY_NOTIFIER */
+
+ FUNCRIDSPLIT(visibility_notifier)
+ FUNC2(visibility_notifier_set_aabb, RID, const AABB &)
+ FUNC3(visibility_notifier_set_callbacks, RID, const Callable &, const Callable &)
+
#undef server_name
#undef ServerName
//from now on, calls forwarded to this singleton
@@ -549,7 +513,7 @@ public:
/* OCCLUDER */
FUNCRIDSPLIT(occluder)
- FUNC3(occluder_set_mesh, RID, const PackedVector3Array &, const PackedInt32Array &);
+ FUNC3(occluder_set_mesh, RID, const PackedVector3Array &, const PackedInt32Array &)
#undef server_name
#undef ServerName
@@ -576,9 +540,9 @@ public:
FUNC1RC(RID, viewport_get_texture, RID)
- FUNC2(viewport_set_hide_scenario, RID, bool)
- FUNC2(viewport_set_hide_canvas, RID, bool)
+ FUNC2(viewport_set_disable_2d, RID, bool)
FUNC2(viewport_set_disable_environment, RID, bool)
+ FUNC2(viewport_set_disable_3d, RID, bool)
FUNC2(viewport_attach_camera, RID, RID)
FUNC2(viewport_set_scenario, RID, RID)
@@ -703,7 +667,6 @@ public:
FUNCRIDSPLIT(scenario)
- FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
FUNC2(scenario_set_environment, RID, RID)
FUNC2(scenario_set_camera_effects, RID, RID)
FUNC2(scenario_set_fallback_environment, RID, RID)
@@ -723,9 +686,9 @@ public:
FUNC2(instance_set_custom_aabb, RID, AABB)
FUNC2(instance_attach_skeleton, RID, RID)
- FUNC2(instance_set_exterior, RID, bool)
FUNC2(instance_set_extra_visibility_margin, RID, real_t)
+ FUNC2(instance_set_visibility_parent, RID, RID)
// don't use these in a game!
FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
@@ -736,8 +699,7 @@ public:
FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
FUNC2(instance_geometry_set_material_override, RID, RID)
- FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
- FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
+ FUNC5(instance_geometry_set_visibility_range, RID, float, float, float, float)
FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int)
FUNC2(instance_geometry_set_lod_bias, RID, float)
@@ -807,6 +769,8 @@ public:
FUNC3(canvas_item_add_particles, RID, RID, RID)
FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
FUNC2(canvas_item_add_clip_ignore, RID, bool)
+ FUNC5(canvas_item_add_animation_slice, RID, double, double, double, double)
+
FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
FUNC2(canvas_item_set_z_index, RID, int)
FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
@@ -820,6 +784,8 @@ public:
FUNC2(canvas_item_set_use_parent_material, RID, bool)
+ FUNC5(canvas_item_set_visibility_notifier, RID, bool, const Rect2 &, const Callable &, const Callable &)
+
FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
FUNCRIDSPLIT(canvas_light)
@@ -887,11 +853,6 @@ public:
#undef WRITE_ACTION
#undef SYNC_DEBUG
- /* BLACK BARS */
-
- virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) override;
- virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) override;
-
/* FREE */
virtual void free(RID p_rid) override {
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index c0d9988e85..2dda506bac 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -30,6 +30,8 @@
#include "rendering_server_globals.h"
+bool RenderingServerGlobals::threaded = false;
+
RendererStorage *RenderingServerGlobals::storage = nullptr;
RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;
RendererCompositor *RenderingServerGlobals::rasterizer = nullptr;
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index a28a0f5180..63755e6125 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -41,6 +41,8 @@ class RendererScene;
class RenderingServerGlobals {
public:
+ static bool threaded;
+
static RendererStorage *storage;
static RendererCanvasRender *canvas_render;
static RendererCompositor *rasterizer;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 8ed774f8e7..9b2ba36358 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -631,7 +631,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
if (!_is_number(last_char)) {
return _make_token(TK_ERROR, "Invalid (integer) numeric constant");
}
- if (!str.is_valid_integer()) {
+ if (!str.is_valid_int()) {
return _make_token(TK_ERROR, "Invalid numeric constant");
}
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index af66e32e06..4120e04ee1 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -447,7 +447,7 @@ public:
virtual DataType get_datatype() const override { return datatype_cache; }
virtual String get_datatype_name() const override { return String(struct_name); }
- virtual int get_array_size() const override { return array_size; }
+ virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
virtual bool is_indexed() const override { return index_expression != nullptr; }
ArrayNode() :
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 35f1b05796..c4e7511374 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -92,6 +92,10 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
+
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = constt(ShaderLanguage::TYPE_BOOL);
@@ -131,6 +135,10 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
+
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);