summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-09-09 17:50:51 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 12:01:21 +0100
commit9d7b7f931b6924399903e4954a0c32d59c15d4c3 (patch)
tree9e20293eab891fea4c5441fe5679ec2f79bced00 /servers
parent69e83e4815545e485350505668a4b9b83346f5bc (diff)
Reflection probes working
Diffstat (limited to 'servers')
-rw-r--r--servers/visual/rasterizer.h21
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp115
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h12
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp291
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.h72
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward.glsl199
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl15
-rw-r--r--servers/visual/visual_server_scene.cpp60
-rw-r--r--servers/visual/visual_server_scene.h4
-rw-r--r--servers/visual/visual_server_viewport.cpp6
-rw-r--r--servers/visual/visual_server_viewport.h1
-rw-r--r--servers/visual_server.cpp3
12 files changed, 521 insertions, 278 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 7423d3ca38..fe682618a4 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -38,6 +38,7 @@
#include "core/self_list.h"
class RasterizerScene {
+
public:
/* SHADOW ATLAS API */
@@ -218,10 +219,15 @@ public:
virtual void light_instance_mark_visible(RID p_light_instance) = 0;
virtual bool light_instances_can_render_shadow_cube() const { return true; }
+ virtual RID reflection_atlas_create() = 0;
+ virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0;
+
virtual RID reflection_probe_instance_create(RID p_probe) = 0;
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0;
+ virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
- virtual void reflection_probe_instance_begin_render(RID p_instance) = 0;
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
virtual RID gi_probe_instance_create() = 0;
@@ -229,7 +235,7 @@ public:
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) = 0;
- virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+ virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
@@ -246,6 +252,9 @@ public:
};
class RasterizerStorage {
+
+ Color default_clear_color;
+
public:
/* TEXTURE API */
@@ -620,6 +629,14 @@ public:
static RasterizerStorage *base_singleton;
+ void set_default_clear_color(const Color &p_color) {
+ default_clear_color = p_color;
+ }
+
+ Color get_default_clear_color() const {
+ return default_clear_color;
+ }
+
RasterizerStorage();
virtual ~RasterizerStorage() {}
};
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
index e1aec58b96..be5b8f1845 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
@@ -614,6 +614,30 @@ void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements,
uint32_t spot_count = 0;
uint32_t decal_count = 0;
+ if (!e->instance->reflection_probe_instances.empty()) {
+
+ uint32_t rpi_count = e->instance->reflection_probe_instances.size();
+ const RID *rpi_ptrs = e->instance->reflection_probe_instances.ptr();
+
+ for (uint32_t j = 0; j < rpi_count; j++) {
+ if (render_pass != reflection_probe_instance_get_render_pass(rpi_ptrs[j])) {
+ continue; //not rendered this frame
+ }
+
+ RID base = reflection_probe_instance_get_probe(rpi_ptrs[j]);
+
+ uint32_t mask = storage->reflection_probe_get_cull_mask(base);
+ if (!(mask & id.mask)) {
+ continue; //masked
+ }
+
+ if (reflection_count < 8) {
+ id.omni_light_indices[omni_count] = reflection_probe_instance_get_render_index(rpi_ptrs[j]);
+ reflection_count++;
+ }
+ }
+ }
+
if (!e->instance->light_instances.empty()) {
uint32_t light_count = e->instance->light_instances.size();
const RID *light_ptrs = e->instance->light_instances.ptr();
@@ -832,12 +856,12 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
}
}
-void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas) {
+void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas) {
//CameraMatrix projection = p_cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
CameraMatrix correction;
- correction.set_depth_correction();
+ correction.set_depth_correction(!p_reflection_probe.is_valid());
CameraMatrix projection = correction * p_cam_projection;
//store camera into ubo
@@ -909,7 +933,17 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
}
} else {
- if (p_render_target.is_valid()) {
+
+ if (p_reflection_probe.is_valid() && !storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
+ scene_state.ubo.use_ambient_light = true;
+ Color clear_color = storage->get_default_clear_color();
+ clear_color = clear_color.to_linear();
+ scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
+ scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
+ scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
+ scene_state.ubo.ambient_light_color_energy[3] = 1.0;
+
+ } else if (p_render_target.is_valid()) {
scene_state.ubo.use_ambient_light = true;
Color clear_color = storage->render_target_get_clear_request_color(p_render_target);
clear_color = clear_color.to_linear();
@@ -1284,11 +1318,11 @@ void RasterizerSceneForwardRD::_draw_sky(RD::DrawListID p_draw_list, RD::Framebu
void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) {
- for (uint32_t i = 0; i < p_reflection_probe_cull_count; i++) {
+ for (int i = 0; i < p_reflection_probe_cull_count; i++) {
RID rpi = p_reflection_probe_cull_result[i];
- if (i >= scene_state.max_reflections) {
+ if (i >= (int)scene_state.max_reflections) {
reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
continue;
}
@@ -1304,14 +1338,14 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r
reflection_ubo.box_extents[0] = extents.x;
reflection_ubo.box_extents[1] = extents.y;
reflection_ubo.box_extents[2] = extents.z;
- reflection_ubo.box_extents[3] = 0;
+ reflection_ubo.index = reflection_probe_instance_get_atlas_index(rpi);
Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
reflection_ubo.box_offset[0] = origin_offset.x;
reflection_ubo.box_offset[1] = origin_offset.y;
reflection_ubo.box_offset[2] = origin_offset.z;
- reflection_ubo.box_offset[3] = 0;
+ reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe);
float intensity = storage->reflection_probe_get_intensity(base_probe);
bool interior = storage->reflection_probe_is_interior(base_probe);
@@ -1350,6 +1384,8 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r
Transform transform = reflection_probe_instance_get_transform(rpi);
Transform proj = (p_camera_inverse_transform * transform).inverse();
store_transform(proj, reflection_ubo.local_matrix);
+
+ reflection_probe_instance_set_render_pass(rpi, render_pass);
}
if (p_reflection_probe_cull_count) {
@@ -1357,7 +1393,7 @@ void RasterizerSceneForwardRD::_setup_reflections(RID *p_reflection_probe_cull_r
}
}
-void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas) {
+void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows) {
uint32_t light_count = 0;
scene_state.ubo.directional_light_count = 0;
@@ -1406,7 +1442,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.shadow_color[1] = shadow_col.g;
light_data.shadow_color[2] = shadow_col.b;
- light_data.shadow_enabled = storage->light_has_shadow(base);
+ light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
if (light_data.shadow_enabled) {
@@ -1481,7 +1517,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
Color shadow_color = storage->light_get_shadow_color(base);
- bool has_shadow = storage->light_has_shadow(base);
+ bool has_shadow = p_using_shadows && storage->light_has_shadow(base);
light_data.shadow_color_enabled[0] = CLAMP(uint32_t(shadow_color.r * 255), 0, 255);
light_data.shadow_color_enabled[1] = CLAMP(uint32_t(shadow_color.g * 255), 0, 255);
light_data.shadow_color_enabled[2] = CLAMP(uint32_t(shadow_color.b * 255), 0, 255);
@@ -1492,7 +1528,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
light_data.atlas_rect[2] = 0;
light_data.atlas_rect[3] = 0;
- if (storage->light_has_shadow(base) && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
+ if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
// fill in the shadow information
Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
@@ -1540,7 +1576,7 @@ void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_lig
}
}
-void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
@@ -1569,8 +1605,14 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
glBindTexture(GL_TEXTURE_2D, reflection_atlas->color);
}
#endif
+
+ bool using_shadows = true;
+
if (p_reflection_probe.is_valid()) {
scene_state.ubo.reflection_multiplier = 0.0;
+ if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_reflection_probe))) {
+ using_shadows = false;
+ }
} else {
scene_state.ubo.reflection_multiplier = 1.0;
}
@@ -1605,13 +1647,17 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass);
alpha_framebuffer = opaque_framebuffer;
+ if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
+ p_environment = RID(); //no environment on interiors
+ }
+
} else {
ERR_FAIL(); //bug?
}
- _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas);
+ _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows);
_setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment);
- _setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas);
+ _setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas);
#if 0
for (int i = 0; i < p_light_cull_count; i++) {
@@ -1983,12 +2029,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
} break;
}
} else {
- if (render_target.is_valid()) {
+
+ if (p_reflection_probe.is_valid() && !storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) {
+ clear_color = storage->get_default_clear_color();
+ } else if (render_target.is_valid()) {
clear_color = storage->render_target_get_clear_request_color(render_target);
}
}
- _setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, RID());
+ _setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, p_reflection_atlas);
render_list.sort_by_key(false);
@@ -2236,7 +2285,7 @@ void RasterizerSceneForwardRD::_render_shadow(RID p_framebuffer, InstanceBase **
scene_state.ubo.z_far = p_zfar;
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
- _setup_environment(RID(), RID(), p_projection, p_transform, true, Vector2(1, 1), RID());
+ _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID());
render_list.clear();
@@ -2363,8 +2412,22 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
}
{
+
+ RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID();
RD::Uniform u;
u.binding = 11;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ if (ref_texture.is_valid()) {
+ u.ids.push_back(ref_texture);
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+ }
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 12;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(scene_state.light_buffer);
uniforms.push_back(u);
@@ -2372,7 +2435,7 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
{
RD::Uniform u;
- u.binding = 12;
+ u.binding = 13;
u.type = RD::UNIFORM_TYPE_TEXTURE;
if (p_shadow_atlas.is_valid()) {
u.ids.push_back(shadow_atlas_get_texture(p_shadow_atlas));
@@ -2384,7 +2447,7 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
{
RD::Uniform u;
- u.binding = 13;
+ u.binding = 14;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(scene_state.directional_light_buffer);
uniforms.push_back(u);
@@ -2392,7 +2455,7 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
{
RD::Uniform u;
- u.binding = 14;
+ u.binding = 15;
u.type = RD::UNIFORM_TYPE_TEXTURE;
if (directional_shadow_get_texture().is_valid()) {
u.ids.push_back(directional_shadow_get_texture());
@@ -2425,18 +2488,6 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
}
- uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
-
- if (textures_per_stage <= 16) {
- //ARM pretty much, and very old Intel GPUs under Linux
- scene_state.max_reflection_probes_per_instance = 4; //sad
- } else {
- //maximum 8
- scene_state.max_reflection_probes_per_instance = 8;
- }
-
- defines += "\n#define MAX_REFLECTION_PROBES " + itos(scene_state.max_reflection_probes_per_instance) + "\n";
-
uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
{ //reflections
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
index 3cf83f7035..c8166c3f88 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
@@ -209,8 +209,10 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
/* Scene State UBO */
struct ReflectionData { //should always be 128 bytes
- float box_extents[4];
- float box_offset[4];
+ float box_extents[3];
+ float index;
+ float box_offset[3];
+ uint32_t mask;
float params[4]; // intensity, 0, interior , boxproject
float ambient[4]; // ambient color, energy
float local_matrix[16]; // up to here for spot and omni, rest is for directional
@@ -480,8 +482,8 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
};
- void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas);
- void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas);
+ void _setup_environment(RID p_render_target, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas);
+ void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
void _fill_instances(RenderList::Element **p_elements, int p_element_count);
@@ -494,7 +496,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
void _draw_sky(RD::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, float p_alpha);
protected:
- virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+ virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
public:
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
index 1c035d5d55..63b65a8a15 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -4,38 +4,17 @@
void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) {
- if (rd.radiance.is_valid()) {
- //if size changes, everything must be cleared
- RD::get_singleton()->free(rd.radiance);
- //everything else gets dependency, erase, so just clean it up
- rd.radiance = RID();
- rd.layers.clear();
- rd.radiance_base_cubemap = RID();
- }
+ rd.layers.clear();
+ rd.radiance_base_cubemap = RID();
}
-void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, bool p_quality) {
+void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer) {
//recreate radiance and all data
- int mipmaps = Image::get_image_required_mipmaps(p_size, p_size, Image::FORMAT_RGBAH) + 1;
- if (!p_quality) {
- //use less mipmaps
- mipmaps = MIN(8, mipmaps);
- }
+ int mipmaps = p_mipmaps;
uint32_t w = p_size, h = p_size;
- if (sky_use_cubemap_array) {
- //array (higher quality, 6 times more memory)
- RD::TextureFormat tf;
- tf.array_layers = roughness_layers * 6;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
- tf.mipmaps = mipmaps;
- tf.width = w;
- tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- rd.radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ if (p_use_array) {
for (int i = 0; i < roughness_layers; i++) {
ReflectionData::Layer layer;
@@ -47,7 +26,7 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
mm.size.width = mmw;
mm.size.height = mmh;
for (int k = 0; k < 6; k++) {
- mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.radiance, i * 6 + k, j);
+ mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6 + k, j);
Vector<RID> fbtex;
fbtex.push_back(mm.views[k]);
mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
@@ -62,17 +41,6 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
} else {
//regular cubemap, lower quality (aliasing, less memory)
- RD::TextureFormat tf;
- tf.array_layers = 6;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.type = RD::TEXTURE_TYPE_CUBE;
- tf.mipmaps = roughness_layers;
- tf.width = w;
- tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- rd.radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
ReflectionData::Layer layer;
uint32_t mmw = w;
uint32_t mmh = h;
@@ -82,7 +50,7 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
mm.size.width = mmw;
mm.size.height = mmh;
for (int k = 0; k < 6; k++) {
- mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.radiance, k, j);
+ mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + k, j);
Vector<RID> fbtex;
fbtex.push_back(mm.views[k]);
mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
@@ -95,11 +63,14 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size,
rd.layers.push_back(layer);
}
- rd.radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.radiance, 0, 0, RD::TEXTURE_SLICE_CUBEMAP);
+ rd.radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP);
}
void RasterizerSceneRD::_create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality) {
+#ifndef _MSC_VER
+#warning TODO, should probably use this algorithm instead. Volunteers? - https://www.ppsloan.org/publications/ggx_filtering.pdf / https://github.com/dariomanesku/cmft
+#endif
if (sky_use_cubemap_array) {
if (p_quality) {
@@ -148,9 +119,9 @@ void RasterizerSceneRD::_create_reflection_from_panorama(ReflectionData &rd, RID
}
}
-void RasterizerSceneRD::_create_reflection_from_base_mipmap(ReflectionData &rd, bool p_quality, int p_cube_side) {
+void RasterizerSceneRD::_create_reflection_from_base_mipmap(ReflectionData &rd, bool p_use_arrays, bool p_quality, int p_cube_side) {
- if (sky_use_cubemap_array) {
+ if (p_use_arrays) {
if (p_quality) {
//render directly to the layers
@@ -220,6 +191,10 @@ void RasterizerSceneRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
}
sky->radiance_size = p_radiance_size;
_sky_invalidate(sky);
+ if (sky->radiance.is_valid()) {
+ RD::get_singleton()->free(sky->radiance);
+ sky->radiance = RID();
+ }
_clear_reflection_data(sky->reflection);
}
@@ -242,6 +217,10 @@ void RasterizerSceneRD::sky_set_texture(RID p_sky, RID p_panorama) {
if (sky->panorama.is_valid()) {
sky->panorama = RID();
+ if (sky->radiance.is_valid()) {
+ RD::get_singleton()->free(sky->radiance);
+ sky->radiance = RID();
+ }
_clear_reflection_data(sky->reflection);
}
@@ -260,8 +239,45 @@ void RasterizerSceneRD::_update_dirty_skys() {
//update sky configuration if texture is missing
- if (sky->reflection.radiance.is_null()) {
- _update_reflection_data(sky->reflection, sky->radiance_size, sky->mode == VS::SKY_MODE_QUALITY);
+ if (sky->radiance.is_null()) {
+ int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1;
+ if (sky->mode != VS::SKY_MODE_QUALITY) {
+ //use less mipmaps
+ mipmaps = MIN(8, mipmaps);
+ }
+
+ uint32_t w = sky->radiance_size, h = sky->radiance_size;
+
+ if (sky_use_cubemap_array) {
+ //array (higher quality, 6 times more memory)
+ RD::TextureFormat tf;
+ tf.array_layers = roughness_layers * 6;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+ tf.mipmaps = mipmaps;
+ tf.width = w;
+ tf.height = h;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ _update_reflection_data(sky->reflection, sky->radiance_size, mipmaps, true, sky->radiance, 0);
+
+ } else {
+ //regular cubemap, lower quality (aliasing, less memory)
+ RD::TextureFormat tf;
+ tf.array_layers = 6;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.type = RD::TEXTURE_TYPE_CUBE;
+ tf.mipmaps = roughness_layers;
+ tf.width = w;
+ tf.height = h;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ _update_reflection_data(sky->reflection, sky->radiance_size, mipmaps, false, sky->radiance, 0);
+ }
}
RID panorama_texture = storage->texture_get_rd_texture(sky->panorama);
@@ -295,7 +311,7 @@ RID RasterizerSceneRD::sky_get_radiance_texture_rd(RID p_sky) const {
Sky *sky = sky_owner.getornull(p_sky);
ERR_FAIL_COND_V(!sky, RID());
- return sky->reflection.radiance;
+ return sky->radiance;
}
RID RasterizerSceneRD::environment_create() {
@@ -469,6 +485,42 @@ bool RasterizerSceneRD::is_environment(RID p_env) const {
////////////////////////////////////////////////////////////
+RID RasterizerSceneRD::reflection_atlas_create() {
+
+ ReflectionAtlas ra;
+ ra.count = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_count");
+ ra.size = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_size");
+
+ return reflection_atlas_owner.make_rid(ra);
+}
+
+void RasterizerSceneRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
+
+ ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas);
+ ERR_FAIL_COND(!ra);
+
+ if (ra->size == p_reflection_size && ra->count == p_reflection_count) {
+ return; //no changes
+ }
+
+ if (ra->reflection.is_valid()) {
+ //clear and invalidate everything
+ RD::get_singleton()->free(ra->reflection);
+ ra->reflection = RID();
+
+ for (int i = 0; i < ra->reflections.size(); i++) {
+ if (ra->reflections[i].owner.is_null()) {
+ continue;
+ }
+ reflection_probe_release_atlas_index(ra->reflections[i].owner);
+ //rp->atlasindex clear
+ }
+
+ ra->reflections.clear();
+ }
+}
+
+////////////////////////
RID RasterizerSceneRD::reflection_probe_instance_create(RID p_probe) {
ReflectionProbeInstance rpi;
rpi.probe = p_probe;
@@ -483,6 +535,22 @@ void RasterizerSceneRD::reflection_probe_instance_set_transform(RID p_instance,
rpi->dirty = true;
}
+void RasterizerSceneRD::reflection_probe_release_atlas_index(RID p_instance) {
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!rpi);
+
+ if (rpi->atlas.is_null()) {
+ return; //nothing to release
+ }
+ ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ ERR_FAIL_COND(!atlas);
+ ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size());
+ atlas->reflections.write[rpi->atlas_index].owner = RID();
+ rpi->atlas_index = -1;
+ rpi->atlas = RID();
+}
+
bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
@@ -496,52 +564,93 @@ bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) {
return true;
}
- if (rpi->current_resolution != storage->reflection_probe_get_resolution(rpi->probe)) {
- return true;
- }
-
if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS) {
return true;
}
- return false;
+ return rpi->atlas_index == -1;
}
-void RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance) {
+bool RasterizerSceneRD::reflection_probe_instance_has_reflection(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND(!rpi);
- rpi->rendering = true;
- rpi->processing_side = 0;
+ ERR_FAIL_COND_V(!rpi, false);
- int probe_resolution = storage->reflection_probe_get_resolution(rpi->probe);
- if (rpi->current_resolution != probe_resolution) {
- //need to re-create everything
- _clear_reflection_data(rpi->reflection);
- _update_reflection_data(rpi->reflection, probe_resolution, storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ONCE);
+ return rpi->atlas.is_valid();
+}
- rpi->current_resolution = probe_resolution;
+bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
- if (rpi->depth_buffer.is_valid()) {
- RD::get_singleton()->free(rpi->depth_buffer);
- }
+ ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_reflection_atlas);
+
+ ERR_FAIL_COND_V(!atlas, false);
+
+ if (atlas->reflection.is_null()) {
{
+ //reflection atlas was unused, create:
RD::TextureFormat tf;
- 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;
- tf.width = probe_resolution;
- tf.height = probe_resolution;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ tf.array_layers = 6 * atlas->count;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+ tf.mipmaps = roughness_layers;
+ tf.width = atlas->size;
+ tf.height = atlas->size;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+ {
- rpi->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::TextureFormat tf;
+ tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
+ tf.width = atlas->size;
+ tf.height = atlas->size;
+ tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ atlas->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
+ atlas->reflections.resize(atlas->count);
+ for (int i = 0; i < atlas->count; i++) {
+ _update_reflection_data(atlas->reflections.write[i].data, atlas->size, roughness_layers, false, atlas->reflection, i * 6);
+ for (int j = 0; j < 6; j++) {
+ Vector<RID> fb;
+ fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]);
+ fb.push_back(atlas->depth_buffer);
+ atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb);
+ }
+ }
+ }
- for (int i = 0; i < 6; i++) {
- Vector<RID> fb;
- fb.push_back(rpi->reflection.layers[0].mipmaps[0].views[i]);
- fb.push_back(rpi->depth_buffer);
- rpi->render_fb[i] = RD::get_singleton()->framebuffer_create(fb);
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+
+ if (rpi->atlas_index == -1) {
+ for (int i = 0; i < atlas->reflections.size(); i++) {
+ if (atlas->reflections[i].owner.is_null()) {
+ rpi->atlas_index = i;
+ break;
+ }
+ }
+ //find the one used last
+ if (rpi->atlas_index == -1) {
+ //everything is in use, find the one least used via LRU
+ uint64_t pass_min = 0;
+
+ for (int i = 0; i < atlas->reflections.size(); i++) {
+ ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.getornull(atlas->reflections[i].owner);
+ if (rpi2->last_pass < pass_min) {
+ pass_min = rpi2->last_pass;
+ rpi->atlas_index = i;
+ }
+ }
}
}
+
+ rpi->atlas = p_reflection_atlas;
+ rpi->rendering = true;
+ rpi->dirty = false;
+ rpi->processing_side = 0;
+
+ return true;
}
bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instance) {
@@ -549,15 +658,22 @@ bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instanc
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, false);
ERR_FAIL_COND_V(!rpi->rendering, false);
+ ERR_FAIL_COND_V(rpi->atlas.is_null(), false);
+
+ ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ if (!atlas || rpi->atlas_index == -1) {
+ //does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering)
+ rpi->rendering = false;
+ return false;
+ }
- _create_reflection_from_base_mipmap(rpi->reflection, storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ONCE, rpi->processing_side);
+ _create_reflection_from_base_mipmap(atlas->reflections.write[rpi->atlas_index].data, false, storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ONCE, rpi->processing_side);
rpi->processing_side++;
if (rpi->processing_side == 6) {
rpi->rendering = false;
rpi->processing_side = 0;
-
return true;
} else {
return false;
@@ -568,7 +684,9 @@ uint32_t RasterizerSceneRD::reflection_probe_instance_get_resolution(RID p_insta
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, 0);
- return rpi->current_resolution;
+ ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ ERR_FAIL_COND_V(!atlas, 0);
+ return atlas->size;
}
RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) {
@@ -576,7 +694,9 @@ RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance,
ERR_FAIL_COND_V(!rpi, RID());
ERR_FAIL_INDEX_V(p_index, 6, RID());
- return rpi->render_fb[p_index];
+ ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas);
+ ERR_FAIL_COND_V(!atlas, RID());
+ return atlas->reflections[rpi->atlas_index].fbs[p_index];
}
///////////////////////////////////////////////////////////
@@ -591,8 +711,8 @@ void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(p_size < 0);
-
p_size = next_power_of_2(p_size);
+ p_size = MAX(p_size, 1 << roughness_layers);
if (p_size == shadow_atlas->size)
return;
@@ -1097,12 +1217,12 @@ bool RasterizerSceneRD::is_using_radiance_cubemap_array() const {
return sky_use_cubemap_array;
}
-void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
+void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb && p_render_buffers.is_valid());
- _render_scene(rb->data, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_probe, p_reflection_probe_pass);
+ _render_scene(rb ? rb->data : (RenderBufferData *)NULL, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_environment, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
}
void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
@@ -1289,14 +1409,21 @@ bool RasterizerSceneRD::free(RID p_rid) {
} else if (environment_owner.owns(p_rid)) {
//not much to delete, just free it
environment_owner.free(p_rid);
+ } else if (reflection_atlas_owner.owns(p_rid)) {
+ reflection_atlas_set_size(p_rid, 0, 0);
+ reflection_atlas_owner.free(p_rid);
} else if (reflection_probe_instance_owner.owns(p_rid)) {
//not much to delete, just free it
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid);
- _clear_reflection_data(rpi->reflection);
+ reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
} else if (sky_owner.owns(p_rid)) {
_update_dirty_skys();
Sky *sky = sky_owner.getornull(p_rid);
+ if (sky->radiance.is_valid()) {
+ RD::get_singleton()->free(sky->radiance);
+ sky->radiance = RID();
+ }
_clear_reflection_data(sky->reflection);
sky_owner.free(p_rid);
} else if (light_instance_owner.owns(p_rid)) {
@@ -1340,7 +1467,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
sky_ggx_samples_quality = GLOBAL_GET("rendering/quality/reflections/ggx_samples");
sky_ggx_samples_realtime = GLOBAL_GET("rendering/quality/reflections/ggx_samples_realtime");
sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");
- sky_use_cubemap_array = false;
+ // sky_use_cubemap_array = false;
}
RasterizerSceneRD::~RasterizerSceneRD() {
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
index a6d3d6b4d1..a1897cabe1 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
@@ -15,7 +15,7 @@ protected:
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
- virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
+ virtual void _render_scene(RenderBufferData *p_buffer_data, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0;
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0;
private:
@@ -24,7 +24,6 @@ private:
RasterizerStorageRD *storage;
struct ReflectionData {
- RID radiance;
struct Layer {
struct Mipmap {
@@ -40,13 +39,14 @@ private:
};
void _clear_reflection_data(ReflectionData &rd);
- void _update_reflection_data(ReflectionData &rd, int p_size, bool p_quality);
+ void _update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer);
void _create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality);
- void _create_reflection_from_base_mipmap(ReflectionData &rd, bool p_quality, int p_cube_side);
+ void _create_reflection_from_base_mipmap(ReflectionData &rd, bool p_use_arrays, bool p_quality, int p_cube_side);
void _update_reflection_mipmaps(ReflectionData &rd, bool p_quality);
/* SKY */
struct Sky {
+ RID radiance;
int radiance_size = 256;
VS::SkyMode mode = VS::SKY_MODE_QUALITY;
RID panorama;
@@ -66,22 +66,41 @@ private:
mutable RID_Owner<Sky> sky_owner;
- /* REFLECTION PROBE INSTANCE */
+ /* REFLECTION ATLAS */
- struct ReflectionProbeInstance {
+ struct ReflectionAtlas {
- RID probe;
+ int count = 0;
+ int size = 0;
- ReflectionData reflection;
+ RID reflection;
RID depth_buffer;
- RID render_fb[6];
- int current_resolution = 0;
+ struct Reflection {
+ RID owner;
+ ReflectionData data;
+ RID fbs[6];
+ };
+
+ Vector<Reflection> reflections;
+ };
+
+ RID_Owner<ReflectionAtlas> reflection_atlas_owner;
+
+ /* REFLECTION PROBE INSTANCE */
+
+ struct ReflectionProbeInstance {
+
+ RID probe;
+ int atlas_index = -1;
+ RID atlas;
bool dirty = true;
bool rendering = false;
int processing_side = 0;
+ uint32_t render_step = 0;
+ uint64_t last_pass = 0;
uint32_t render_index = 0;
Transform transform;
@@ -453,10 +472,20 @@ 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);
+ _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) {
+ ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas);
+ ERR_FAIL_COND_V(!atlas, RID());
+ return atlas->reflection;
+ }
+
virtual RID reflection_probe_instance_create(RID p_probe);
virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
+ virtual void reflection_probe_release_atlas_index(RID p_instance);
virtual bool reflection_probe_instance_needs_redraw(RID p_instance);
- virtual void reflection_probe_instance_begin_render(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);
uint32_t reflection_probe_instance_get_resolution(RID p_instance);
@@ -482,6 +511,19 @@ public:
return rpi->render_index;
}
+ _FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!rpi);
+ rpi->last_pass = p_render_pass;
+ }
+
+ _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, 0);
+
+ return rpi->last_pass;
+ }
+
_FORCE_INLINE_ Transform reflection_probe_instance_get_transform(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
ERR_FAIL_COND_V(!rpi, Transform());
@@ -489,11 +531,11 @@ public:
return rpi->transform;
}
- _FORCE_INLINE_ RID reflection_probe_instance_get_texture(RID p_instance) {
+ _FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) {
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
- ERR_FAIL_COND_V(!rpi, RID());
+ ERR_FAIL_COND_V(!rpi, -1);
- return rpi->reflection.radiance;
+ return rpi->atlas_index;
}
RID gi_probe_instance_create() { return RID(); }
@@ -504,7 +546,7 @@ public:
RID render_buffers_create();
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa);
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+ void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
index 1bed9f9672..d64276a2bf 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
@@ -710,6 +710,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
+
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo,float roughness, float metallic, float specular,float p_blob_intensity,
#ifdef LIGHT_TRANSMISSION_USED
vec3 transmission,
@@ -781,6 +782,86 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 a
diffuse_light, specular_light);
}
+void reflection_process(uint ref_index, vec3 vertex, vec3 normal,float roughness,vec3 ambient_light,vec3 specular_light,inout vec4 ambient_accum, inout vec4 reflection_accum) {
+
+ vec3 box_extents = reflections.data[ref_index].box_extents;
+ vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
+
+ if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
+ return;
+ }
+
+ vec3 ref_vec = normalize(reflect(vertex, normal));
+
+ vec3 inner_pos = abs(local_pos / box_extents);
+ float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
+ //make blend more rounded
+ blend = mix(length(inner_pos), blend, blend);
+ blend *= blend;
+ blend = max(0.0, 1.0 - blend);
+
+ if (reflections.data[ref_index].params.x > 0.0) { // compute reflection
+
+ vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
+
+ if (reflections.data[ref_index].params.w > 0.5) { //box project
+
+ vec3 nrdir = normalize(local_ref_vec);
+ vec3 rbmax = (box_extents - local_pos) / nrdir;
+ vec3 rbmin = (-box_extents - local_pos) / nrdir;
+
+ vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0)));
+
+ float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
+ vec3 posonbox = local_pos + nrdir * fa;
+ local_ref_vec = posonbox - reflections.data[ref_index].box_offset;
+ }
+
+ 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;
+
+ if (reflections.data[ref_index].params.z < 0.5) {
+ reflection.rgb = mix(specular_light, reflection.rgb, blend);
+ }
+
+ reflection.rgb *= reflections.data[ref_index].params.x;
+ reflection.a = blend;
+ reflection.rgb *= reflection.a;
+
+ reflection_accum += reflection;
+ }
+
+#ifndef USE_LIGHTMAP
+ if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox
+
+ vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
+
+ vec4 ambient_out;
+
+ ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec,reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
+
+ ambient_out.a = blend;
+ ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a);
+ if (reflections.data[ref_index].params.z < 0.5) {
+ ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
+ }
+
+ ambient_out.rgb *= ambient_out.a;
+ ambient_accum += ambient_out;
+ } else {
+
+ vec4 ambient_out;
+ ambient_out.a = blend;
+ ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
+ if (reflections.data[ref_index].params.z < 0.5) {
+ ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
+ }
+ ambient_out.rgb *= ambient_out.a;
+ ambient_accum += ambient_out;
+ }
+#endif //USE_LIGHTMAP
+}
void main() {
#ifdef MODE_DUAL_PARABOLOID
@@ -976,126 +1057,28 @@ FRAGMENT_SHADER_CODE
//lightmap capture
-#if 0
+
{ // process reflections
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
- for (uint i = 0; i < MAX_REFLECTION_PROBES; i++) {
- if (i >= draw_data.reflection_probe_count) {
- break;
- }
+ uint reflection_probe_count = instances.data[instance_index].flags & INSTANCE_FLAGS_FORWARD_MASK;
- uint ref_index;
- if (i<4) {
- if (i<2) {
- ref_index=draw_data.reflection_probe_indices[0];
- } else {
- ref_index=draw_data.reflection_probe_indices[1];
- }
- } else {
- if (i<6) {
- ref_index=draw_data.reflection_probe_indices[2];
- } else {
- ref_index=draw_data.reflection_probe_indices[3];
- }
- }
- ref_index>>=(i&1)*16;
- ref_index&=0xFFFF;
-
- vec3 box_extents = reflections.data[ref_index].box_extents.xyz;
- vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
-
- if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box
- continue;
- }
-
- vec3 ref_vec = normalize(reflect(vertex, normal));
-
- vec3 inner_pos = abs(local_pos / box_extents);
- float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
- //make blend more rounded
- blend = mix(length(inner_pos), blend, blend);
- blend *= blend;
- blend = max(0.0, 1.0 - blend);
-
- if (reflections.data[ref_index].params.x > 0.0) { // compute reflection
-
- vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
-
- if (reflections.data[ref_index].params.w > 0.5) { //box project
-
- vec3 nrdir = normalize(local_ref_vec);
- vec3 rbmax = (box_extents - local_pos) / nrdir;
- vec3 rbmin = (-box_extents - local_pos) / nrdir;
+ for (uint i = 0; i < reflection_probe_count; i++) {
- vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0)));
- float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
- vec3 posonbox = local_pos + nrdir * fa;
- local_ref_vec = posonbox - reflections.data[ref_index].box_offset.xyz;
- }
-
- vec4 reflection;
-
-#ifdef USE_RADIANCE_CUBEMAP_ARRAY
-
- float lod,layer_blend;
- layer_blend = modf(roughness * MAX_ROUGHNESS_LOD, lod);
- reflection.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod)).rgb;
- reflection.rgb = mix(reflection.rgb,texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, lod+1)).rgb,layer_blend);
+ uint ref_index = instances.data[instance_index].reflection_probe_indices[i>>1];
-#else
- reflection.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
-
-#endif
-
- if (reflections.data[ref_index].params.z < 0.5) {
- reflection.rgb = mix(specular_light, reflection.rgb, blend);
- }
-
- reflection.rgb *= reflections.data[ref_index].params.x;
- reflection.a = blend;
- reflection.rgb *= reflection.a;
-
- reflection_accum += reflection;
+ if (bool(i&1)) {
+ ref_index>>=16;
+ } else {
+ ref_index&=0xFFFF;
}
-#ifndef USE_LIGHTMAP
- if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox
-
- vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz;
-
- vec4 ambient_out;
-#ifdef USE_RADIANCE_CUBEMAP_ARRAY
- ambient_out.rgb = texture(samplerCubeArray(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, MAX_ROUGHNESS_LOD)).rgb;
-#else
- ambient_out.rgb = textureLod(samplerCube(reflection_probes[i],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), local_amb_vec, MAX_ROUGHNESS_LOD).rgb;
-#endif //USE_RADIANCE_CUBEMAP_ARRAY
-
- ambient_out.a = blend;
- ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a);
- if (reflections.data[ref_index].params.z < 0.5) {
- ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
- }
-
- ambient_out.rgb *= ambient_out.a;
- ambient_accum += ambient_out;
- } else {
-
- vec4 ambient_out;
- ambient_out.a = blend;
- ambient_out.rgb = reflections.data[ref_index].ambient.rgb;
- if (reflections.data[ref_index].params.z < 0.5) {
- ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
- }
- ambient_out.rgb *= ambient_out.a;
- ambient_accum += ambient_out;
- }
-#endif //USE_LIGHTMAP
+ reflection_process(ref_index,vertex,normal,roughness,ambient_light,specular_light,ambient_accum,reflection_accum);
}
@@ -1111,7 +1094,7 @@ FRAGMENT_SHADER_CODE
}
-#endif //0
+
{
#if defined(DIFFUSE_TOON)
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
index 3e6249e4cb..d6b6aa4301 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
@@ -145,8 +145,10 @@ layout(set=0,binding=9,std430) buffer Instances {
struct ReflectionData {
- vec4 box_extents;
- vec4 box_offset;
+ vec3 box_extents;
+ float index;
+ vec3 box_offset;
+ uint mask;
vec4 params; // intensity, 0, interior , boxproject
vec4 ambient; // ambient color, energy
mat4 local_matrix; // up to here for spot and omni, rest is for directional
@@ -157,6 +159,7 @@ layout(set=0,binding=10,std140) uniform ReflectionProbeData {
ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
} reflections;
+layout(set=0,binding=11) uniform textureCubeArray reflection_atlas;
struct LightData { //this structure needs to be 128 bits
@@ -172,11 +175,11 @@ struct LightData { //this structure needs to be 128 bits
mat4 shadow_matrix;
};
-layout(set=0,binding=11,std140) uniform Lights {
+layout(set=0,binding=12,std140) uniform Lights {
LightData data[MAX_LIGHT_DATA_STRUCTS];
} lights;
-layout(set=0,binding=12) uniform texture2D shadow_atlas;
+layout(set=0,binding=13) uniform texture2D shadow_atlas;
struct DirectionalLightData {
@@ -198,11 +201,11 @@ struct DirectionalLightData {
};
-layout(set=0,binding=13,std140) uniform DirectionalLights {
+layout(set=0,binding=14,std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
} directional_lights;
-layout(set=0,binding=14) uniform texture2D directional_shadow_atlas;
+layout(set=0,binding=15) uniform texture2D directional_shadow_atlas;
/*
layout(set=0,binding=15,std430) buffer Skeletons {
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index d060043b40..3f33ec945c 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -268,7 +268,7 @@ RID VisualServerScene::scenario_create() {
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);
VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);
-
+ scenario->reflection_atlas = VSG::scene_render->reflection_atlas_create();
return scenario_rid;
}
@@ -293,6 +293,13 @@ void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_
scenario->fallback_environment = p_environment;
}
+void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {
+
+ Scenario *scenario = scenario_owner.getornull(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);
+}
+
/* INSTANCING API */
void VisualServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
@@ -510,6 +517,8 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) {
}
} break;
case VS::INSTANCE_REFLECTION_PROBE: {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
+ VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
} break;
case VS::INSTANCE_GI_PROBE: {
@@ -1808,7 +1817,7 @@ void VisualServerScene::render_camera(RID p_render_buffers, Ref<ARVRInterface> &
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, p_scenario, p_shadow_atlas, RID(), -1);
};
-void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe) {
+void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, 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
@@ -1894,8 +1903,10 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
reflection_probe->reflection_dirty = false;
}
- reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
- reflection_probe_cull_count++;
+ if (VSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
+ reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
+ reflection_probe_cull_count++;
+ }
}
}
}
@@ -2015,7 +2026,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
//check shadow..
if (light) {
- if (p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) {
+ if (p_using_shadows && p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) {
lights_with_shadow[directional_shadow_count++] = E->get();
}
//add to list
@@ -2031,7 +2042,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
}
- { //setup shadow maps
+ if (p_using_shadows) { //setup shadow maps
//SortArray<Instance*,_InstanceLightsort> sorter;
//sorter.sort(light_cull_result,light_cull_count);
@@ -2148,7 +2159,7 @@ void VisualServerScene::_render_scene(RID p_render_buffers, const Transform p_ca
/* PROCESS GEOMETRY AND DRAW SCENE */
- VSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, environment, p_shadow_atlas, p_reflection_probe, p_reflection_probe_pass);
+ VSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, environment, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass);
}
void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
@@ -2162,7 +2173,7 @@ void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario,
environment = scenario->environment;
else
environment = scenario->fallback_environment;
- VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, RID(), 0);
+ VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, scenario->reflection_atlas, RID(), 0);
#endif
}
@@ -2176,18 +2187,28 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
if (p_step == 0) {
- VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance);
+ if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
+ return true; //all full
+ }
}
if (p_step >= 0 && p_step < 6) {
static const Vector3 view_normals[6] = {
- Vector3(-1, 0, 0),
Vector3(+1, 0, 0),
- Vector3(0, -1, 0),
+ Vector3(-1, 0, 0),
Vector3(0, +1, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, 0, +1),
+ Vector3(0, 0, -1)
+ };
+ static const Vector3 view_up[6] = {
+ Vector3(0, -1, 0),
+ Vector3(0, -1, 0),
+ Vector3(0, 0, +1),
Vector3(0, 0, -1),
- Vector3(0, 0, +1)
+ Vector3(0, -1, 0),
+ Vector3(0, -1, 0)
};
Vector3 extents = VSG::storage->reflection_probe_get_extents(p_instance->base);
@@ -2203,15 +2224,6 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
CameraMatrix cm;
cm.set_perspective(90, 1, 0.01, max_distance);
- static const Vector3 view_up[6] = {
- Vector3(0, -1, 0),
- Vector3(0, -1, 0),
- Vector3(0, 0, -1),
- Vector3(0, 0, +1),
- Vector3(0, -1, 0),
- Vector3(0, -1, 0)
- };
-
Transform local_view;
local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]);
@@ -2219,12 +2231,13 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
RID shadow_atlas;
- if (VSG::storage->reflection_probe_renders_shadows(p_instance->base)) {
+ bool use_shadows = VSG::storage->reflection_probe_renders_shadows(p_instance->base);
+ if (use_shadows) {
shadow_atlas = scenario->reflection_probe_shadow_atlas;
}
- _prepare_scene(xform, cm, false, RID(), VSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance);
+ _prepare_scene(xform, cm, false, RID(), VSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows);
_render_scene(RID(), xform, cm, false, RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step);
} else {
@@ -3465,6 +3478,7 @@ bool VisualServerScene::free(RID p_rid) {
instance_set_scenario(scenario->instances.first()->self()->self, RID());
}
VSG::scene_render->free(scenario->reflection_probe_shadow_atlas);
+ VSG::scene_render->free(scenario->reflection_atlas);
scenario_owner.free(p_rid);
memdelete(scenario);
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index 0f73f42153..2fadd778be 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -115,6 +115,7 @@ public:
RID environment;
RID fallback_environment;
RID reflection_probe_shadow_atlas;
+ RID reflection_atlas;
SelfList<Instance>::List instances;
@@ -131,6 +132,7 @@ public:
virtual void scenario_set_debug(RID p_scenario, VS::ScenarioDebugMode p_debug_mode);
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
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);
/* INSTANCING API */
@@ -475,7 +477,7 @@ public:
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
- void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe);
+ void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
index 5d2441be7b..75a90d988b 100644
--- a/servers/visual/visual_server_viewport.cpp
+++ b/servers/visual/visual_server_viewport.cpp
@@ -83,7 +83,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
int scenario_canvas_max_layer = 0;
- Color bgcolor = clear_color;
+ Color bgcolor = VSG::storage->get_default_clear_color();
if (!p_viewport->hide_canvas && !p_viewport->disable_environment && VSG::scene->scenario_owner.owns(p_viewport->scenario)) {
@@ -295,7 +295,7 @@ void VisualServerViewport::draw_viewports() {
#endif
if (Engine::get_singleton()->is_editor_hint()) {
- clear_color = GLOBAL_GET("rendering/environment/default_clear_color");
+ set_default_clear_color(GLOBAL_GET("rendering/environment/default_clear_color"));
}
//sort viewports
@@ -719,7 +719,7 @@ bool VisualServerViewport::free(RID p_rid) {
}
void VisualServerViewport::set_default_clear_color(const Color &p_color) {
- clear_color = p_color;
+ VSG::storage->set_default_clear_color(p_color);
}
VisualServerViewport::VisualServerViewport() {
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
index eecbe0d1db..30b53f3935 100644
--- a/servers/visual/visual_server_viewport.h
+++ b/servers/visual/visual_server_viewport.h
@@ -148,7 +148,6 @@ public:
Vector<Viewport *> active_viewports;
private:
- Color clear_color;
void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye);
void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO);
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index af29f14b77..66e0d67938 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -2302,6 +2302,9 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/reflections/ggx_samples.mobile", 128);
GLOBAL_DEF("rendering/quality/reflections/ggx_samples_realtime", 64);
GLOBAL_DEF("rendering/quality/reflections/ggx_samples_realtime.mobile", 16);
+ GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 256);
+ GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size.mobile", 128);
+ GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_count", 64);
GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false);
GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true);