summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp67
-rw-r--r--servers/physics_2d/area_pair_2d_sw.h6
-rw-r--r--servers/physics_3d/area_pair_3d_sw.cpp69
-rw-r--r--servers/physics_3d/area_pair_3d_sw.h6
-rw-r--r--servers/register_server_types.cpp2
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h5
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp4
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp24
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp6
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp16
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h1
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp31
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h13
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp5
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.h1
-rw-r--r--servers/rendering/renderer_rd/shaders/blur_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl3
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/sky.glsl15
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl38
-rw-r--r--servers/rendering/renderer_viewport.cpp84
-rw-r--r--servers/rendering/renderer_viewport.h6
-rw-r--r--servers/rendering/rendering_device.h1
-rw-r--r--servers/rendering/rendering_server_default.h1
-rw-r--r--servers/rendering_server.cpp13
-rw-r--r--servers/rendering_server.h11
-rw-r--r--servers/xr/xr_interface.cpp70
-rw-r--r--servers/xr/xr_interface.h27
-rw-r--r--servers/xr/xr_interface_extension.cpp241
-rw-r--r--servers/xr/xr_interface_extension.h105
-rw-r--r--servers/xr_server.cpp16
-rw-r--r--servers/xr_server.h1
38 files changed, 685 insertions, 223 deletions
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index 5ca16cb6fc..4f1148c26f 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -33,7 +33,7 @@
bool AreaPair2DSW::setup(real_t p_step) {
bool result = false;
- if (area->interacts_with(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
+ if (area->collides_with(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
result = true;
}
@@ -109,46 +109,51 @@ AreaPair2DSW::~AreaPair2DSW() {
//////////////////////////////////
bool Area2Pair2DSW::setup(real_t p_step) {
- bool result = false;
- if (area_a->interacts_with(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
- result = true;
+ bool result_a = area_a->collides_with(area_b);
+ bool result_b = area_b->collides_with(area_a);
+ if ((result_a || result_b) && !CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
+ result_a = false;
+ result_b = false;
}
- process_collision = false;
- if (result != colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
- process_collision = true;
- } else if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ bool process_collision = false;
+
+ process_collision_a = false;
+ if (result_a != colliding_a) {
+ if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ process_collision_a = true;
process_collision = true;
}
+ colliding_a = result_a;
+ }
- colliding = result;
+ process_collision_b = false;
+ if (result_b != colliding_b) {
+ if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ process_collision_b = true;
+ process_collision = true;
+ }
+ colliding_b = result_b;
}
return process_collision;
}
bool Area2Pair2DSW::pre_solve(real_t p_step) {
- if (!process_collision) {
- return false;
+ if (process_collision_a) {
+ if (colliding_a) {
+ area_a->add_area_to_query(area_b, shape_b, shape_a);
+ } else {
+ area_a->remove_area_from_query(area_b, shape_b, shape_a);
+ }
}
- if (colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ if (process_collision_b) {
+ if (colliding_b) {
area_b->add_area_to_query(area_a, shape_a, shape_b);
- }
-
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
- area_a->add_area_to_query(area_b, shape_b, shape_a);
- }
- } else {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ } else {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}
-
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
- area_a->remove_area_from_query(area_b, shape_b, shape_a);
- }
}
return false; // Never do any post solving.
@@ -168,16 +173,18 @@ Area2Pair2DSW::Area2Pair2DSW(Area2DSW *p_area_a, int p_shape_a, Area2DSW *p_area
}
Area2Pair2DSW::~Area2Pair2DSW() {
- if (colliding) {
- if (area_b->has_area_monitor_callback()) {
- area_b->remove_area_from_query(area_a, shape_a, shape_b);
- }
-
+ if (colliding_a) {
if (area_a->has_area_monitor_callback()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}
+ if (colliding_b) {
+ if (area_b->has_area_monitor_callback()) {
+ area_b->remove_area_from_query(area_a, shape_a, shape_b);
+ }
+ }
+
area_a->remove_constraint(this);
area_b->remove_constraint(this);
}
diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h
index 4632a307d9..66e9f1afee 100644
--- a/servers/physics_2d/area_pair_2d_sw.h
+++ b/servers/physics_2d/area_pair_2d_sw.h
@@ -57,8 +57,10 @@ class Area2Pair2DSW : public Constraint2DSW {
Area2DSW *area_b = nullptr;
int shape_a = 0;
int shape_b = 0;
- bool colliding = false;
- bool process_collision = false;
+ bool colliding_a = false;
+ bool colliding_b = false;
+ bool process_collision_a = false;
+ bool process_collision_b = false;
public:
virtual bool setup(real_t p_step) override;
diff --git a/servers/physics_3d/area_pair_3d_sw.cpp b/servers/physics_3d/area_pair_3d_sw.cpp
index e740565da6..bf4f0035b4 100644
--- a/servers/physics_3d/area_pair_3d_sw.cpp
+++ b/servers/physics_3d/area_pair_3d_sw.cpp
@@ -33,7 +33,7 @@
bool AreaPair3DSW::setup(real_t p_step) {
bool result = false;
- if (area->interacts_with(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
+ if (area->collides_with(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
result = true;
}
@@ -109,46 +109,51 @@ AreaPair3DSW::~AreaPair3DSW() {
////////////////////////////////////////////////////
bool Area2Pair3DSW::setup(real_t p_step) {
- bool result = false;
- if (area_a->interacts_with(area_b) && CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
- result = true;
+ bool result_a = area_a->collides_with(area_b);
+ bool result_b = area_b->collides_with(area_a);
+ if ((result_a || result_b) && !CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
+ result_a = false;
+ result_b = false;
}
- process_collision = false;
- if (result != colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
- process_collision = true;
- } else if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ bool process_collision = false;
+
+ process_collision_a = false;
+ if (result_a != colliding_a) {
+ if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
+ process_collision_a = true;
process_collision = true;
}
+ colliding_a = result_a;
+ }
- colliding = result;
+ process_collision_b = false;
+ if (result_b != colliding_b) {
+ if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ process_collision_b = true;
+ process_collision = true;
+ }
+ colliding_b = result_b;
}
return process_collision;
}
bool Area2Pair3DSW::pre_solve(real_t p_step) {
- if (!process_collision) {
- return false;
+ if (process_collision_a) {
+ if (colliding_a) {
+ area_a->add_area_to_query(area_b, shape_b, shape_a);
+ } else {
+ area_a->remove_area_from_query(area_b, shape_b, shape_a);
+ }
}
- if (colliding) {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ if (process_collision_b) {
+ if (colliding_b) {
area_b->add_area_to_query(area_a, shape_a, shape_b);
- }
-
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
- area_a->add_area_to_query(area_b, shape_b, shape_a);
- }
- } else {
- if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
+ } else {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}
-
- if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
- area_a->remove_area_from_query(area_b, shape_b, shape_a);
- }
}
return false; // Never do any post solving.
@@ -168,16 +173,18 @@ Area2Pair3DSW::Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area
}
Area2Pair3DSW::~Area2Pair3DSW() {
- if (colliding) {
- if (area_b->has_area_monitor_callback()) {
- area_b->remove_area_from_query(area_a, shape_a, shape_b);
- }
-
+ if (colliding_a) {
if (area_a->has_area_monitor_callback()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}
+ if (colliding_b) {
+ if (area_b->has_area_monitor_callback()) {
+ area_b->remove_area_from_query(area_a, shape_a, shape_b);
+ }
+ }
+
area_a->remove_constraint(this);
area_b->remove_constraint(this);
}
@@ -187,7 +194,7 @@ Area2Pair3DSW::~Area2Pair3DSW() {
bool AreaSoftBodyPair3DSW::setup(real_t p_step) {
bool result = false;
if (
- area->interacts_with(soft_body) &&
+ area->collides_with(soft_body) &&
CollisionSolver3DSW::solve_static(
soft_body->get_shape(soft_body_shape),
soft_body->get_transform() * soft_body->get_shape_transform(soft_body_shape),
diff --git a/servers/physics_3d/area_pair_3d_sw.h b/servers/physics_3d/area_pair_3d_sw.h
index 8cc9e9ad63..4572dcbb23 100644
--- a/servers/physics_3d/area_pair_3d_sw.h
+++ b/servers/physics_3d/area_pair_3d_sw.h
@@ -58,8 +58,10 @@ class Area2Pair3DSW : public Constraint3DSW {
Area3DSW *area_b;
int shape_a;
int shape_b;
- bool colliding = false;
- bool process_collision = false;
+ bool colliding_a = false;
+ bool colliding_b = false;
+ bool process_collision_a = false;
+ bool process_collision_b = false;
public:
virtual bool setup(real_t p_step) override;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 8e86957d9b..41c8b45113 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -72,6 +72,7 @@
#include "servers/rendering/shader_types.h"
#include "text_server.h"
#include "xr/xr_interface.h"
+#include "xr/xr_interface_extension.h"
#include "xr/xr_positional_tracker.h"
#include "xr_server.h"
@@ -138,6 +139,7 @@ void register_server_types() {
GDREGISTER_VIRTUAL_CLASS(RenderingDevice);
GDREGISTER_VIRTUAL_CLASS(XRInterface);
+ GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions.
GDREGISTER_CLASS(XRPositionalTracker);
GDREGISTER_CLASS(AudioStream);
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 80d843227b..236eb5e596 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -812,6 +812,7 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
@@ -864,6 +865,7 @@ void EffectsRD::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_colo
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
tonemap.push_constant.use_debanding = p_settings.use_debanding;
+ tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
RD::get_singleton()->draw_list_bind_render_pipeline(p_subpass_draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, p_dst_format_id, false, RD::get_singleton()->draw_list_get_current_pass()));
RD::get_singleton()->draw_list_bind_uniform_set(p_subpass_draw_list, _get_uniform_set_for_input(p_source_color), 0);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index c8d4cb7ad4..0db0919dbc 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -255,7 +255,7 @@ private:
float exposure; // 4 - 84
float white; // 4 - 88
float auto_exposure_grey; // 4 - 92
- uint32_t pad2; // 4 - 96
+ float luminance_multiplier; // 4 - 96
float pixel_size[2]; // 8 - 104
uint32_t use_fxaa; // 4 - 108
@@ -308,7 +308,7 @@ private:
float exposure_adjust;
float min_luminance;
float max_luminance;
- float pad[1];
+ uint32_t pad1;
};
struct LuminanceReduceFragment {
@@ -818,6 +818,7 @@ public:
bool use_auto_exposure = false;
float auto_exposure_grey = 0.5;
RID exposure_texture;
+ float luminance_multiplier = 1.0;
bool use_bcs = false;
float brightness = 1.0;
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 be18a73989..a24860996c 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
@@ -683,6 +683,8 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
default_shader = storage->shader_allocate();
storage->shader_initialize(default_shader);
storage->shader_set_code(default_shader, R"(
+// Default 3D material shader (clustered).
+
shader_type spatial;
void vertex() {
@@ -712,6 +714,8 @@ void fragment() {
storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
storage->shader_set_code(overdraw_material_shader, R"(
+// 3D editor Overdraw debug draw mode shader (clustered).
+
shader_type spatial;
render_mode blend_add, unshaded;
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 2064d9c5c5..1b4052b622 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -86,12 +86,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) {
clear();
- bool is_half_resolution = false; // Set this once we support this feature.
-
msaa = p_msaa;
+ Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
+
width = p_width;
height = p_height;
+ bool is_scaled = (target_size.width != p_width) || (target_size.height != p_height);
view_count = p_view_count;
color = p_color_buffer;
@@ -124,7 +125,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
passes.push_back(pass);
color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
- if (!is_half_resolution) {
+ if (!is_scaled) {
// - add blit to 2D pass
fb.push_back(p_target_buffer); // 2 - target buffer
@@ -211,7 +212,7 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count);
}
- if (!is_half_resolution) {
+ if (!is_scaled) {
// - add blit to 2D pass
fb.push_back(p_target_buffer); // 3 - target buffer
RD::FramebufferPass blit_pass;
@@ -271,6 +272,12 @@ bool RenderForwardMobile::free(RID p_rid) {
/* Render functions */
+float RenderForwardMobile::_render_buffers_get_luminance_multiplier() {
+ // On mobile renderer we need to multiply source colors by 2 due to using a UNORM buffer
+ // and multiplying by the output color during 3D rendering by 0.5
+ return 2.0;
+}
+
RD::DataFormat RenderForwardMobile::_render_buffers_get_color_format() {
// Using 32bit buffers enables AFBC on mobile devices which should have a definite performance improvement (MALI G710 and newer support this on 64bit RTs)
return RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
@@ -491,7 +498,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
bool using_subpass_transparent = true;
bool using_subpass_post_process = true;
- bool is_half_resolution = false; // Set this once we support this feature.
bool using_ssr = false; // I don't think we support this in our mobile renderer so probably should phase it out
bool using_sss = false; // I don't think we support this in our mobile renderer so probably should phase it out
@@ -512,7 +518,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
- if (is_half_resolution) {
+ if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
// can't do blit subpass
using_subpass_post_process = false;
} else if (env && (env->glow_enabled || env->auto_exposure || camera_effects_uses_dof(p_render_data->camera_effects))) {
@@ -631,7 +637,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RID sky_rid = env->sky;
if (sky_rid.is_valid()) {
- sky.update(env, projection, p_render_data->cam_transform, time);
+ sky.update(env, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@@ -750,9 +756,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
CameraMatrix correction;
correction.set_depth_correction(true);
CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
} else {
- sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
}
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
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 764d8e80df..38f80c5347 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -202,6 +202,7 @@ protected:
}
};
+ virtual float _render_buffers_get_luminance_multiplier() override;
virtual RD::DataFormat _render_buffers_get_color_format() override;
virtual bool _render_buffers_can_be_storage() override;
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 735014a2ec..14b3b6d9aa 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
@@ -665,6 +665,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.global_buffer_array_variable = "global_variables.data";
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
+ actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
+
compiler.initialize(actions);
}
@@ -673,6 +675,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
default_shader = storage->shader_allocate();
storage->shader_initialize(default_shader);
storage->shader_set_code(default_shader, R"(
+// Default 3D material shader (mobile).
+
shader_type spatial;
void vertex() {
@@ -701,6 +705,8 @@ void fragment() {
storage->shader_initialize(overdraw_material_shader);
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
storage->shader_set_code(overdraw_material_shader, R"(
+// 3D editor Overdraw debug draw mode shader (mobile).
+
shader_type spatial;
render_mode blend_add, unshaded;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index f8aefdb29c..3af5047854 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -2575,6 +2575,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
storage->shader_initialize(default_canvas_group_shader);
storage->shader_set_code(default_canvas_group_shader, R"(
+// Default CanvasGroup shader.
+
shader_type canvas_item;
void fragment() {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 8496ef631b..fa66ed85a9 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -2237,6 +2237,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
}
+ tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
@@ -2301,6 +2302,7 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.use_debanding = rb->use_debanding;
tonemap.texture_size = Vector2i(rb->width, rb->height);
+ tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
storage->get_effects()->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
@@ -2573,6 +2575,10 @@ float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID
return rb->volumetric_fog->spread;
}
+float RendererSceneRenderRD::_render_buffers_get_luminance_multiplier() {
+ return 1.0;
+}
+
RD::DataFormat RendererSceneRenderRD::_render_buffers_get_color_format() {
return RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
}
@@ -2585,6 +2591,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+
+ // Should we add an overrule per viewport?
rb->width = p_width;
rb->height = p_height;
rb->render_target = p_render_target;
@@ -2631,8 +2639,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
}
- tf.width = p_width;
- tf.height = p_height;
+ tf.width = rb->width;
+ tf.height = rb->height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
tf.array_layers = rb->view_count; // create a layer for every view
@@ -2654,10 +2662,10 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
}
RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
- rb->data->configure(rb->texture, rb->depth_texture, target_texture, p_width, p_height, p_msaa, p_view_count);
+ rb->data->configure(rb->texture, rb->depth_texture, target_texture, rb->width, rb->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);
+ rb->cluster_builder->setup(Size2i(rb->width, rb->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);
}
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 37533baecf..eb61af517a 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -1190,6 +1190,7 @@ public:
/* render buffers */
+ virtual float _render_buffers_get_luminance_multiplier();
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
virtual RID render_buffers_create() override;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 9e85608f1e..da84f615b2 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -259,7 +259,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
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) {
+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, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
@@ -276,6 +276,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
sky_push_constant.position[2] = p_position.z;
sky_push_constant.multiplier = p_multiplier;
sky_push_constant.time = p_time;
+ sky_push_constant.luminance_multiplier = p_luminance_multiplier;
store_transform_3x3(p_orientation, sky_push_constant.orientation);
RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
@@ -855,6 +856,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
storage->shader_initialize(sky_shader.default_shader);
storage->shader_set_code(sky_shader.default_shader, R"(
+// Default sky shader.
+
shader_type sky;
void sky() {
@@ -942,6 +945,8 @@ void sky() {
storage->shader_initialize(sky_scene_state.fog_shader);
storage->shader_set_code(sky_scene_state.fog_shader, R"(
+// Default clear color sky shader.
+
shader_type sky;
uniform vec4 clear_color;
@@ -1191,7 +1196,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
}
-void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time) {
+void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
Sky *sky = get_sky(p_env->sky);
@@ -1283,7 +1288,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);
- _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, 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, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1302,7 +1307,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);
- _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, 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, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1317,7 +1322,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);
- _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, 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, multiplier, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1435,7 +1440,7 @@ 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);
- _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);
+ _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, 1.0);
RD::get_singleton()->draw_list_end();
}
@@ -1448,7 +1453,7 @@ 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);
- _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);
+ _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, 1.0);
RD::get_singleton()->draw_list_end();
}
@@ -1462,11 +1467,11 @@ 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);
- _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, 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, 1.0);
RD::get_singleton()->draw_list_end();
}
-void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1542,7 +1547,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
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);
- _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);
+ _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, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@@ -1555,12 +1560,12 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
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);
- _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);
+ _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, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
}
-void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
ERR_FAIL_COND(!p_env);
ERR_FAIL_COND(p_view_count == 0);
@@ -1636,7 +1641,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
- _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin);
+ _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
}
void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 7b670bddd5..7f563c9bc4 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -100,7 +100,8 @@ private:
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
+ float luminance_multiplier; // 4 - 104
+ float pad[2]; // 8 - 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.
};
@@ -138,7 +139,7 @@ private:
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);
+ 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, float p_luminance_multiplier);
public:
struct SkySceneState {
@@ -293,10 +294,10 @@ public:
~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, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
- void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
- void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time);
+ void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ 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); // only called by clustered renderer
+ void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
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 8cc20618fc..14a5a01054 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -9398,6 +9398,8 @@ RendererStorageRD::RendererStorageRD() {
particles_shader.default_shader = shader_allocate();
shader_initialize(particles_shader.default_shader);
shader_set_code(particles_shader.default_shader, R"(
+// Default particles shader.
+
shader_type particles;
void process() {
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index bad37f5c25..b95d4b642c 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -1165,6 +1165,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0];
bool is_texture_func = false;
+ bool is_screen_texture = false;
if (onode->op == SL::OP_STRUCT) {
code += _mkid(vnode->name);
} else if (onode->op == SL::OP_CONSTRUCT) {
@@ -1197,6 +1198,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
const SL::VariableNode *varnode = static_cast<const SL::VariableNode *>(onode->arguments[i]);
StringName texture_uniform = varnode->name;
+ is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
String sampler_name;
@@ -1236,6 +1238,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
}
}
code += ")";
+ if (is_screen_texture && actions.apply_luminance_multiplier) {
+ code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))";
+ }
} break;
case SL::OP_INDEX: {
code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.h b/servers/rendering/renderer_rd/shader_compiler_rd.h
index 2da127ffa3..0fe9047967 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.h
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.h
@@ -95,6 +95,7 @@ public:
String global_buffer_array_variable;
String instance_uniform_index_variable;
uint32_t base_varying_index = 0;
+ bool apply_luminance_multiplier = false;
};
private:
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/blur_raster.glsl
index 0789a4b396..f8b4e3f610 100644
--- a/servers/rendering/renderer_rd/shaders/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/blur_raster.glsl
@@ -38,6 +38,8 @@ layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
layout(location = 0) out vec4 frag_color;
void main() {
+ // We do not apply our color scale for our mobile renderer here, we'll leave our colors at half brightness and apply scale in the tonemap raster.
+
#ifdef MODE_MIPMAP
vec2 pix_size = blur.pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
index ed389ffe56..3cde9923fa 100644
--- a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
@@ -6,6 +6,6 @@ layout(push_constant, binding = 1, std430) uniform PushConstant {
float exposure_adjust;
float min_luminance;
float max_luminance;
- float pad;
+ uint pad1;
}
settings;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 7a11f8904e..edbe1031b7 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -374,6 +374,9 @@ layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
+// not used in clustered renderer but we share some code with the mobile renderer that requires this.
+const float sc_luminance_multiplier = 1.0;
+
#include "scene_forward_clustered_inc.glsl"
/* Varyings */
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 9fa5d3280d..f3db4abe3b 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -969,7 +969,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
vec4 reflection;
- reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb;
+ reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier;
if (reflections.data[ref_index].exterior) {
reflection.rgb = mix(specular_light, reflection.rgb, blend);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 7e2cc8fe01..518b0a6c7f 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -401,6 +401,8 @@ layout(constant_id = 14) const bool sc_disable_fog = false;
#endif //!MODE_RENDER_DEPTH
+layout(constant_id = 15) const float sc_luminance_multiplier = 2.0;
+
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
@@ -1551,12 +1553,15 @@ void main() {
frag_color = vec4(albedo, alpha);
#else // MODE_UNSHADED
frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha);
- //frag_color = vec4(1.0);
#endif // MODE_UNSHADED
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
+ // On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking
+ // We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images
+ frag_color.rgb = frag_color.rgb / sc_luminance_multiplier;
+
#endif //MODE_MULTIPLE_RENDER_TARGETS
#endif //MODE_RENDER_DEPTH
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl
index 41c6325bc5..d07a454ade 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/sky.glsl
@@ -17,6 +17,8 @@ layout(push_constant, binding = 1, std430) uniform Params {
vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
float time;
+ float luminance_multiplier;
+ float pad[2];
}
params;
@@ -55,6 +57,8 @@ layout(push_constant, binding = 1, std430) uniform Params {
vec4 projections[MAX_VIEWS];
vec4 position_multiplier;
float time;
+ float luminance_multiplier;
+ float pad[2];
}
params;
@@ -199,17 +203,17 @@ void main() {
vec3 inverted_cube_normal = cube_normal;
inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR
- half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
+ half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
+ quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
#endif
#else
#ifdef USES_HALF_RES_COLOR
- half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
+ half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
+ quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
#endif
#endif
@@ -246,4 +250,7 @@ void main() {
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
frag_color.a = 0.0;
}
+
+ // For mobile renderer we're dividing by 2.0 as we're using a UNORM buffer
+ frag_color.rgb = frag_color.rgb / params.luminance_multiplier;
}
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index f997101183..4411587116 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -71,7 +71,7 @@ layout(push_constant, binding = 1, std430) uniform Params {
float exposure;
float white;
float auto_exposure_grey;
- uint pad2;
+ float luminance_multiplier;
vec2 pixel_size;
bool use_fxaa;
@@ -298,15 +298,15 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
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;
+ vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
#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;
+ vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
#endif
vec3 rgbM = color;
vec3 luma = vec3(0.299, 0.587, 0.114);
@@ -333,11 +333,11 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
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);
+ 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) * params.luminance_multiplier;
+ 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) * params.luminance_multiplier;
#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);
+ 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) * params.luminance_multiplier;
+ 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) * params.luminance_multiplier;
#endif
float lumaB = dot(rgbB, luma);
@@ -364,11 +364,11 @@ vec3 screen_space_dither(vec2 frag_coord) {
void main() {
#ifdef SUBPASS
// SUBPASS and MULTIVIEW can be combined but in that case we're already reading from the correct layer
- vec3 color = subpassLoad(input_color).rgb;
+ vec3 color = subpassLoad(input_color).rgb * params.luminance_multiplier;
#elif defined(MULTIVIEW)
- vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb;
+ vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb * params.luminance_multiplier;
#else
- vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
+ vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb * params.luminance_multiplier;
#endif
// Exposure
@@ -377,7 +377,7 @@ void main() {
#ifndef SUBPASS
if (params.use_auto_exposure) {
- exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey);
+ exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_grey);
}
#endif
@@ -386,7 +386,7 @@ void main() {
// Early Tonemap & SRGB Conversion
#ifndef SUBPASS
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
- vec3 glow = gather_glow(source_glow, uv_interp);
+ vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier;
color.rgb = mix(color.rgb, glow, params.glow_intensity);
}
@@ -411,7 +411,7 @@ void main() {
// Glow
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
- vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity;
+ vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity * params.luminance_multiplier;
// high dynamic range -> SRGB
glow = apply_tonemapping(glow, params.white);
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 15ce1dbe63..3ede9fed2d 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -71,6 +71,44 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
return xf;
}
+void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
+ if (p_viewport->render_buffers.is_valid()) {
+ if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
+ RSG::scene->free(p_viewport->render_buffers);
+ p_viewport->render_buffers = RID();
+ } else {
+ RS::ViewportScale3D scale_3d = p_viewport->scale_3d;
+ if (Engine::get_singleton()->is_editor_hint()) { // ignore this inside of the editor
+ scale_3d = RS::VIEWPORT_SCALE_3D_DISABLED;
+ }
+
+ int width = p_viewport->size.width;
+ int height = p_viewport->size.height;
+ switch (scale_3d) {
+ case RS::VIEWPORT_SCALE_3D_75_PERCENT: {
+ width = (width * 3) / 4;
+ height = (height * 3) / 4;
+ }; break;
+ case RS::VIEWPORT_SCALE_3D_50_PERCENT: {
+ width = width >> 1;
+ height = height >> 1;
+ }; break;
+ case RS::VIEWPORT_SCALE_3D_33_PERCENT: {
+ width = width / 3;
+ height = height / 3;
+ }; break;
+ case RS::VIEWPORT_SCALE_3D_25_PERCENT: {
+ width = width >> 2;
+ height = height >> 2;
+ }; break;
+ default:
+ break;
+ }
+ RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, width, height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding, p_viewport->get_view_count());
+ }
+ }
+}
+
void RendererViewport::_draw_3d(Viewport *p_viewport) {
RENDER_TIMESTAMP(">Begin Rendering 3D Scene");
@@ -100,7 +138,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
RENDER_TIMESTAMP("<End Rendering 3D Scene");
}
-void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_count) {
+void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (p_viewport->measure_render_time) {
String rt_id = "vp_begin_" + itos(p_viewport->self.get_id());
RSG::storage->capture_timestamp(rt_id);
@@ -142,7 +180,8 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport, uint32_t p_view_coun
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, p_view_count);
+
+ _configure_3d_render_buffers(p_viewport);
}
RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
@@ -544,7 +583,7 @@ void RendererViewport::draw_viewports() {
RSG::storage->render_target_set_as_unused(vp->render_target);
if (vp->use_xr && xr_interface.is_valid()) {
// override our size, make sure it matches our required size and is created as a stereo target
- vp->size = xr_interface->get_render_targetsize();
+ vp->size = xr_interface->get_render_target_size();
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);
@@ -556,7 +595,7 @@ void RendererViewport::draw_viewports() {
RSG::scene->set_debug_draw_mode(vp->debug_draw);
// and draw viewport
- _draw_viewport(vp, view_count);
+ _draw_viewport(vp);
// measure
@@ -580,7 +619,7 @@ void RendererViewport::draw_viewports() {
RSG::scene->set_debug_draw_mode(vp->debug_draw);
// render standard mono camera
- _draw_viewport(vp, 1);
+ _draw_viewport(vp);
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
@@ -648,9 +687,19 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
}
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());
+ _configure_3d_render_buffers(viewport);
+}
+
+void RendererViewport::viewport_set_scale_3d(RID p_viewport, RenderingServer::ViewportScale3D p_scale_3d) {
+ Viewport *viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ if (viewport->scale_3d == p_scale_3d) {
+ return;
}
+
+ viewport->scale_3d = p_scale_3d;
+ _configure_3d_render_buffers(viewport);
}
uint32_t RendererViewport::Viewport::get_view_count() {
@@ -677,14 +726,7 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
viewport->size = Size2(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, view_count);
- }
- }
+ _configure_3d_render_buffers(viewport);
viewport->occlusion_buffer_dirty = true;
}
@@ -915,9 +957,7 @@ void RendererViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa
return;
}
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, viewport->get_view_count());
- }
+ _configure_3d_render_buffers(viewport);
}
void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode) {
@@ -928,9 +968,7 @@ void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::Viewport
return;
}
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, viewport->get_view_count());
- }
+ _configure_3d_render_buffers(viewport);
}
void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) {
@@ -941,9 +979,7 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
return;
}
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, viewport->get_view_count());
- }
+ _configure_3d_render_buffers(viewport);
}
void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) {
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index ac7a35f97d..f6095e18d7 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -49,6 +49,8 @@ public:
bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
+ RS::ViewportScale3D scale_3d = RenderingServer::VIEWPORT_SCALE_3D_DISABLED;
+
Size2i size;
RID camera;
RID scenario;
@@ -192,8 +194,9 @@ public:
int total_draw_calls_used = 0;
private:
+ void _configure_3d_render_buffers(Viewport *p_viewport);
void _draw_3d(Viewport *p_viewport);
- void _draw_viewport(Viewport *p_viewport, uint32_t p_view_count = 1);
+ void _draw_viewport(Viewport *p_viewport);
int occlusion_rays_per_thread = 512;
@@ -204,6 +207,7 @@ public:
void viewport_initialize(RID p_rid);
void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
+ void viewport_set_scale_3d(RID p_viewport, RenderingServer::ViewportScale3D p_scale_3d);
void viewport_set_size(RID p_viewport, int p_width, int p_height);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index e2d207dab2..2cf1f165dd 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -495,6 +495,7 @@ public:
virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const = 0;
virtual bool texture_is_shared(RID p_texture) = 0;
virtual bool texture_is_valid(RID p_texture) = 0;
+ virtual Size2i texture_size(RID p_texture) = 0;
virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index c1336ee42d..3386b99f53 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -526,6 +526,7 @@ public:
FUNCRIDSPLIT(viewport)
FUNC2(viewport_set_use_xr, RID, bool)
+ FUNC2(viewport_set_scale_3d, RID, ViewportScale3D)
FUNC3(viewport_set_size, RID, int, int)
FUNC2(viewport_set_active, RID, bool)
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 222ea9e622..78604dfe8c 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2138,6 +2138,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_create"), &RenderingServer::viewport_create);
ClassDB::bind_method(D_METHOD("viewport_set_use_xr", "viewport", "use_xr"), &RenderingServer::viewport_set_use_xr);
+ ClassDB::bind_method(D_METHOD("viewport_set_scale_3d", "viewport", "scale"), &RenderingServer::viewport_set_scale_3d);
ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &RenderingServer::viewport_set_size);
ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &RenderingServer::viewport_set_active);
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport);
@@ -2255,6 +2256,12 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS);
+ BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_75_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_50_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_33_PERCENT);
+ BIND_ENUM_CONSTANT(VIEWPORT_SCALE_3D_25_PERCENT);
+
/* SKY API */
ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
@@ -2795,6 +2802,12 @@ RenderingServer::RenderingServer() {
"rendering/vulkan/rendering/back_end",
PROPERTY_HINT_ENUM, "Forward Clustered (Supports Desktop Only),Forward Mobile (Supports Desktop and Mobile)"));
+ GLOBAL_DEF("rendering/3d/viewport/scale", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/3d/viewport/scale",
+ PropertyInfo(Variant::INT,
+ "rendering/3d/viewport/scale",
+ PROPERTY_HINT_ENUM, "Disabled,75%,50%,33%,25%"));
+
GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/use_zstd_compression", true);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 545270dcd9..6f80b52faa 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -752,9 +752,19 @@ public:
CANVAS_ITEM_TEXTURE_REPEAT_MAX,
};
+ enum ViewportScale3D {
+ VIEWPORT_SCALE_3D_DISABLED,
+ VIEWPORT_SCALE_3D_75_PERCENT,
+ VIEWPORT_SCALE_3D_50_PERCENT,
+ VIEWPORT_SCALE_3D_33_PERCENT,
+ VIEWPORT_SCALE_3D_25_PERCENT,
+ VIEWPORT_SCALE_3D_MAX,
+ };
+
virtual RID viewport_create() = 0;
virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0;
+ virtual void viewport_set_scale_3d(RID p_viewport, ViewportScale3D p_scale_3d) = 0;
virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0;
virtual void viewport_set_active(RID p_viewport, bool p_active) = 0;
virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0;
@@ -1542,6 +1552,7 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw);
VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale);
+VARIANT_ENUM_CAST(RenderingServer::ViewportScale3D);
VARIANT_ENUM_CAST(RenderingServer::SkyMode);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource);
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 09e8e12f8b..fc1d82a964 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -36,21 +36,19 @@ void XRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_capabilities"), &XRInterface::get_capabilities);
ClassDB::bind_method(D_METHOD("is_primary"), &XRInterface::is_primary);
- ClassDB::bind_method(D_METHOD("set_is_primary", "enable"), &XRInterface::set_is_primary);
+ ClassDB::bind_method(D_METHOD("set_primary", "primary"), &XRInterface::set_primary);
ClassDB::bind_method(D_METHOD("is_initialized"), &XRInterface::is_initialized);
- ClassDB::bind_method(D_METHOD("set_is_initialized", "initialized"), &XRInterface::set_is_initialized);
ClassDB::bind_method(D_METHOD("initialize"), &XRInterface::initialize);
ClassDB::bind_method(D_METHOD("uninitialize"), &XRInterface::uninitialize);
ClassDB::bind_method(D_METHOD("get_tracking_status"), &XRInterface::get_tracking_status);
- ClassDB::bind_method(D_METHOD("get_render_targetsize"), &XRInterface::get_render_targetsize);
+ ClassDB::bind_method(D_METHOD("get_render_target_size"), &XRInterface::get_render_target_size);
ClassDB::bind_method(D_METHOD("get_view_count"), &XRInterface::get_view_count);
ADD_GROUP("Interface", "interface_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_is_primary", "is_primary");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_initialized"), "set_is_initialized", "is_initialized");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_primary", "is_primary");
// we don't have any properties specific to VR yet....
@@ -77,70 +75,48 @@ void XRInterface::_bind_methods() {
BIND_ENUM_CONSTANT(XR_INSUFFICIENT_FEATURES);
BIND_ENUM_CONSTANT(XR_UNKNOWN_TRACKING);
BIND_ENUM_CONSTANT(XR_NOT_TRACKING);
-};
-
-StringName XRInterface::get_name() const {
- return "Unknown";
-};
+}
bool XRInterface::is_primary() {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, false);
return xr_server->get_primary_interface() == this;
-};
+}
-void XRInterface::set_is_primary(bool p_is_primary) {
+void XRInterface::set_primary(bool p_primary) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
- if (p_is_primary) {
+ if (p_primary) {
ERR_FAIL_COND(!is_initialized());
xr_server->set_primary_interface(this);
- } else {
- xr_server->clear_primary_interface_if(this);
- };
-};
-
-void XRInterface::set_is_initialized(bool p_initialized) {
- if (p_initialized) {
- if (!is_initialized()) {
- initialize();
- };
- } else {
- if (is_initialized()) {
- uninitialize();
- };
- };
-};
-
-XRInterface::Tracking_status XRInterface::get_tracking_status() const {
- return tracking_state;
-};
-
-XRInterface::XRInterface() {
- tracking_state = XR_UNKNOWN_TRACKING;
-};
+ } else if (xr_server->get_primary_interface() == this) {
+ xr_server->set_primary_interface(nullptr);
+ }
+}
-XRInterface::~XRInterface() {}
+XRInterface::XRInterface() {}
-// optional render to external texture which enhances performance on those platforms that require us to submit our end result into special textures.
-unsigned int XRInterface::get_external_texture_for_eye(XRInterface::Eyes p_eye) {
- return 0;
-};
+XRInterface::~XRInterface() {}
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool XRInterface::get_anchor_detection_is_enabled() const {
return false;
-};
+}
void XRInterface::set_anchor_detection_is_enabled(bool p_enable) {
- // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
}
int XRInterface::get_camera_feed_id() {
- // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
-
return 0;
-};
+}
+
+/** these are optional, so we want dummies **/
+XRInterface::TrackingStatus XRInterface::get_tracking_status() const {
+ return XR_UNKNOWN_TRACKING;
+}
+
+void XRInterface::notification(int p_what) {
+}
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 6b248c9554..4f5d4bad10 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -68,7 +68,7 @@ public:
EYE_RIGHT
};
- enum Tracking_status { /* tracking status currently based on AR but we can start doing more with this for VR as well */
+ enum TrackingStatus { /* tracking status currently based on AR but we can start doing more with this for VR as well */
XR_NORMAL_TRACKING,
XR_EXCESSIVE_MOTION,
XR_INSUFFICIENT_FEATURES,
@@ -76,26 +76,25 @@ public:
XR_NOT_TRACKING
};
+private:
protected:
_THREAD_SAFE_CLASS_
- Tracking_status tracking_state;
static void _bind_methods();
public:
/** general interface information **/
- virtual StringName get_name() const;
- virtual int get_capabilities() const = 0;
+ virtual StringName get_name() const = 0;
+ virtual uint32_t get_capabilities() const = 0;
bool is_primary();
- void set_is_primary(bool p_is_primary);
+ void set_primary(bool p_is_primary);
virtual bool is_initialized() const = 0; /* returns true if we've initialized this interface */
- void set_is_initialized(bool p_initialized); /* helper function, will call initialize or uninitialize */
virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */
virtual void uninitialize() = 0; /* deinitialize this interface */
- Tracking_status get_tracking_status() const; /* get the status of our current tracking */
+ virtual TrackingStatus get_tracking_status() const; /* get the status of our current tracking */
/** specific to VR **/
// nothing yet
@@ -107,27 +106,25 @@ public:
/** rendering and internal **/
- virtual Size2 get_render_targetsize() = 0; /* returns the recommended render target size per eye for this device */
+ virtual Size2 get_render_target_size() = 0; /* returns the recommended render target size per eye for this device */
virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */
virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) = 0; /* get each view projection matrix */
+ // note, external color/depth/vrs texture support will be added here soon.
+
virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* commit rendered views to the XR interface */
virtual void process() = 0;
- virtual void notification(int p_what) = 0;
+ virtual void notification(int p_what);
XRInterface();
~XRInterface();
-
- // deprecated
- virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye); /* if applicable return external texture to render to */
- virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) = 0; /* output the left or right eye */
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
VARIANT_ENUM_CAST(XRInterface::Eyes);
-VARIANT_ENUM_CAST(XRInterface::Tracking_status);
+VARIANT_ENUM_CAST(XRInterface::TrackingStatus);
-#endif
+#endif // !XR_INTERFACE_H
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
new file mode 100644
index 0000000000..e1519d1463
--- /dev/null
+++ b/servers/xr/xr_interface_extension.cpp
@@ -0,0 +1,241 @@
+/*************************************************************************/
+/* xr_interface_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "xr_interface_extension.h"
+#include "servers/rendering/renderer_compositor.h"
+
+void XRInterfaceExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_name);
+ GDVIRTUAL_BIND(_get_capabilities);
+
+ GDVIRTUAL_BIND(_is_initialized);
+ GDVIRTUAL_BIND(_initialize);
+ GDVIRTUAL_BIND(_uninitialize);
+
+ GDVIRTUAL_BIND(_get_tracking_status);
+
+ ClassDB::bind_method(D_METHOD("add_blit", "render_target", "rect", "use_layer", "layer", "apply_lens_distortion", "eye_center", "k1", "k2", "upscale", "aspect_ratio"), &XRInterfaceExtension::add_blit);
+
+ GDVIRTUAL_BIND(_get_render_target_size);
+ GDVIRTUAL_BIND(_get_view_count);
+ GDVIRTUAL_BIND(_get_camera_transform);
+ GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
+ GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
+
+ GDVIRTUAL_BIND(_commit_views);
+
+ GDVIRTUAL_BIND(_process);
+ GDVIRTUAL_BIND(_notification, "what");
+
+ // we don't have any properties specific to VR yet....
+
+ // but we do have properties specific to AR....
+ GDVIRTUAL_BIND(_get_anchor_detection_is_enabled);
+ GDVIRTUAL_BIND(_set_anchor_detection_is_enabled, "enabled");
+ GDVIRTUAL_BIND(_get_camera_feed_id);
+}
+
+StringName XRInterfaceExtension::get_name() const {
+ StringName name;
+
+ if (GDVIRTUAL_CALL(_get_name, name)) {
+ return name;
+ }
+
+ return "Unknown";
+}
+
+uint32_t XRInterfaceExtension::get_capabilities() const {
+ uint32_t capabilities;
+
+ if (GDVIRTUAL_CALL(_get_capabilities, capabilities)) {
+ return capabilities;
+ }
+
+ return 0;
+}
+
+bool XRInterfaceExtension::is_initialized() const {
+ bool initialised = false;
+
+ if (GDVIRTUAL_CALL(_is_initialized, initialised)) {
+ return initialised;
+ }
+
+ return false;
+}
+
+bool XRInterfaceExtension::initialize() {
+ bool initialised = false;
+
+ if (GDVIRTUAL_CALL(_initialize, initialised)) {
+ return initialised;
+ }
+
+ return false;
+}
+
+void XRInterfaceExtension::uninitialize() {
+ GDVIRTUAL_CALL(_uninitialize);
+}
+
+XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const {
+ uint32_t status;
+
+ if (GDVIRTUAL_CALL(_get_tracking_status, status)) {
+ return TrackingStatus(status);
+ }
+
+ return XR_UNKNOWN_TRACKING;
+}
+
+/** these will only be implemented on AR interfaces, so we want dummies for VR **/
+bool XRInterfaceExtension::get_anchor_detection_is_enabled() const {
+ bool enabled;
+
+ if (GDVIRTUAL_CALL(_get_anchor_detection_is_enabled, enabled)) {
+ return enabled;
+ }
+
+ return false;
+}
+
+void XRInterfaceExtension::set_anchor_detection_is_enabled(bool p_enable) {
+ // don't do anything here, this needs to be implemented on AR interface to enable/disable things like plane detection etc.
+ GDVIRTUAL_CALL(_set_anchor_detection_is_enabled, p_enable);
+}
+
+int XRInterfaceExtension::get_camera_feed_id() {
+ int feed_id;
+
+ if (GDVIRTUAL_CALL(_get_camera_feed_id, feed_id)) {
+ return feed_id;
+ }
+
+ return 0;
+}
+
+Size2 XRInterfaceExtension::get_render_target_size() {
+ Size2 size;
+
+ if (GDVIRTUAL_CALL(_get_render_target_size, size)) {
+ return size;
+ }
+
+ return Size2(0, 0);
+}
+
+uint32_t XRInterfaceExtension::get_view_count() {
+ uint32_t view_count;
+
+ if (GDVIRTUAL_CALL(_get_view_count, view_count)) {
+ return view_count;
+ }
+
+ return 1;
+}
+
+Transform3D XRInterfaceExtension::get_camera_transform() {
+ Transform3D transform;
+
+ if (GDVIRTUAL_CALL(_get_camera_transform, transform)) {
+ return transform;
+ }
+
+ return Transform3D();
+}
+
+Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
+ Transform3D transform;
+
+ if (GDVIRTUAL_CALL(_get_transform_for_view, p_view, p_cam_transform, transform)) {
+ return transform;
+ }
+
+ return Transform3D();
+}
+
+CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+ CameraMatrix cm;
+ PackedFloat64Array arr;
+
+ if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) {
+ ERR_FAIL_COND_V_MSG(arr.size() != 16, CameraMatrix(), "Projection matrix must contain 16 floats");
+ real_t *m = (real_t *)cm.matrix;
+ for (int i = 0; i < 16; i++) {
+ m[i] = arr[i];
+ }
+ return cm;
+ }
+
+ return CameraMatrix();
+}
+
+void XRInterfaceExtension::add_blit(RID p_render_target, Rect2i p_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, float p_k1, float p_k2, float p_upscale, float p_aspect_ratio) {
+ BlitToScreen blit;
+
+ ERR_FAIL_COND_MSG(!can_add_blits, "add_blit can only be called from an XR plugin from within _commit_views!");
+
+ blit.render_target = p_render_target;
+ blit.rect = p_rect;
+
+ blit.multi_view.use_layer = p_use_layer;
+ blit.multi_view.layer = p_layer;
+
+ blit.lens_distortion.apply = p_apply_lens_distortion;
+ blit.lens_distortion.eye_center = p_eye_center;
+ blit.lens_distortion.k1 = p_k1;
+ blit.lens_distortion.k2 = p_k2;
+ blit.lens_distortion.upscale = p_upscale;
+ blit.lens_distortion.aspect_ratio = p_aspect_ratio;
+
+ blits.push_back(blit);
+}
+
+Vector<BlitToScreen> XRInterfaceExtension::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+ // This is just so our XR plugin can add blits...
+ blits.clear();
+ can_add_blits = true;
+
+ if (GDVIRTUAL_CALL(_commit_views, p_render_target, p_screen_rect)) {
+ return blits;
+ }
+
+ can_add_blits = false;
+ return blits;
+}
+
+void XRInterfaceExtension::process() {
+ GDVIRTUAL_CALL(_process);
+}
+
+void XRInterfaceExtension::notification(int p_what) {
+ GDVIRTUAL_CALL(_notification, p_what);
+}
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
new file mode 100644
index 0000000000..ab4d90bfe6
--- /dev/null
+++ b/servers/xr/xr_interface_extension.h
@@ -0,0 +1,105 @@
+/*************************************************************************/
+/* xr_interface_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef XR_INTERFACE_EXTENSION_H
+#define XR_INTERFACE_EXTENSION_H
+
+#include "servers/xr/xr_interface.h"
+
+class XRInterfaceExtension : public XRInterface {
+ GDCLASS(XRInterfaceExtension, XRInterface);
+
+public:
+private:
+ bool can_add_blits = false;
+ Vector<BlitToScreen> blits;
+
+protected:
+ _THREAD_SAFE_CLASS_
+
+ static void _bind_methods();
+
+public:
+ /** general interface information **/
+ virtual StringName get_name() const override;
+ virtual uint32_t get_capabilities() const override;
+
+ GDVIRTUAL0RC(StringName, _get_name);
+ GDVIRTUAL0RC(uint32_t, _get_capabilities);
+
+ virtual bool is_initialized() const override;
+ virtual bool initialize() override;
+ virtual void uninitialize() override;
+
+ GDVIRTUAL0RC(bool, _is_initialized);
+ GDVIRTUAL0R(bool, _initialize);
+ GDVIRTUAL0(_uninitialize);
+
+ virtual TrackingStatus get_tracking_status() const override;
+ GDVIRTUAL0RC(uint32_t, _get_tracking_status);
+
+ /** specific to VR **/
+ // nothing yet
+
+ /** specific to AR **/
+ virtual bool get_anchor_detection_is_enabled() const override;
+ virtual void set_anchor_detection_is_enabled(bool p_enable) override;
+ virtual int get_camera_feed_id() override;
+
+ GDVIRTUAL0RC(bool, _get_anchor_detection_is_enabled);
+ GDVIRTUAL1(_set_anchor_detection_is_enabled, bool);
+ GDVIRTUAL0RC(int, _get_camera_feed_id);
+
+ /** rendering and internal **/
+
+ virtual Size2 get_render_target_size() override;
+ virtual uint32_t get_view_count() override;
+ virtual Transform3D get_camera_transform() override;
+ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
+ virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
+
+ GDVIRTUAL0R(Size2, _get_render_target_size);
+ GDVIRTUAL0R(uint32_t, _get_view_count);
+ GDVIRTUAL0R(Transform3D, _get_camera_transform);
+ GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
+ GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, real_t, real_t, real_t);
+
+ void add_blit(RID p_render_target, Rect2i p_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), float p_k1 = 0.0, float p_k2 = 0.0, float p_upscale = 1.0, float p_aspect_ratio = 1.0);
+ virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
+ GDVIRTUAL2(_commit_views, RID, const Rect2 &);
+
+ virtual void process() override;
+ virtual void notification(int p_what) override;
+
+ GDVIRTUAL0(_process);
+ GDVIRTUAL1(_notification, int);
+};
+
+#endif // !XR_INTERFACE_EXTENSION_H
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index c27656047f..c18a9f8b4e 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -49,7 +49,6 @@ void XRServer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale");
ClassDB::bind_method(D_METHOD("add_interface", "interface"), &XRServer::add_interface);
- ClassDB::bind_method(D_METHOD("clear_primary_interface_if", "interface"), &XRServer::clear_primary_interface_if);
ClassDB::bind_method(D_METHOD("get_interface_count"), &XRServer::get_interface_count);
ClassDB::bind_method(D_METHOD("remove_interface", "interface"), &XRServer::remove_interface);
ClassDB::bind_method(D_METHOD("get_interface", "idx"), &XRServer::get_interface);
@@ -316,17 +315,14 @@ Ref<XRInterface> XRServer::get_primary_interface() const {
};
void XRServer::set_primary_interface(const Ref<XRInterface> &p_primary_interface) {
- ERR_FAIL_COND(p_primary_interface.is_null());
- primary_interface = p_primary_interface;
-
- print_verbose("XR: Primary interface set to: " + primary_interface->get_name());
-};
-
-void XRServer::clear_primary_interface_if(const Ref<XRInterface> &p_primary_interface) {
- if (primary_interface == p_primary_interface) {
+ if (p_primary_interface.is_null()) {
print_verbose("XR: Clearing primary interface");
primary_interface.unref();
- };
+ } else {
+ primary_interface = p_primary_interface;
+
+ print_verbose("XR: Primary interface set to: " + primary_interface->get_name());
+ }
};
uint64_t XRServer::get_last_process_usec() {
diff --git a/servers/xr_server.h b/servers/xr_server.h
index 25431844c2..af183e175d 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -159,7 +159,6 @@ public:
*/
Ref<XRInterface> get_primary_interface() const;
void set_primary_interface(const Ref<XRInterface> &p_primary_interface);
- void clear_primary_interface_if(const Ref<XRInterface> &p_primary_interface); /* this is automatically called if an interface destructs */
/*
Our trackers are objects that expose the orientation and position of physical devices such as controller, anchor points, etc.