summaryrefslogtreecommitdiff
path: root/servers/visual
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual')
-rw-r--r--servers/visual/rasterizer.cpp2
-rw-r--r--servers/visual/rasterizer.h31
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp2
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp49
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_effects_rd.h27
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp697
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h149
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp1179
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.h358
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp520
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.h245
-rw-r--r--servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h14
-rw-r--r--servers/visual/rasterizer_rd/shaders/SCsub1
-rw-r--r--servers/visual/rasterizer_rd/shaders/blur.glsl4
-rw-r--r--servers/visual/rasterizer_rd/shaders/blur_inc.glsl1
-rw-r--r--servers/visual/rasterizer_rd/shaders/copy.glsl93
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward.glsl503
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl158
-rw-r--r--servers/visual/rasterizer_rd/shaders/tonemap.glsl10
-rw-r--r--servers/visual/visual_server_raster.cpp4
-rw-r--r--servers/visual/visual_server_raster.h4
-rw-r--r--servers/visual/visual_server_scene.cpp59
-rw-r--r--servers/visual/visual_server_scene.h2
-rw-r--r--servers/visual/visual_server_wrap_mt.h4
24 files changed, 3451 insertions, 665 deletions
diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp
index 64b5c88699..a3f93a3f8c 100644
--- a/servers/visual/rasterizer.cpp
+++ b/servers/visual/rasterizer.cpp
@@ -47,6 +47,8 @@ void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted)
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependencies.erase(this);
}
+
+ instances.clear();
}
RasterizerScene::InstanceDependency::~InstanceDependency() {
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index c6517a12ed..7423d3ca38 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -46,6 +46,7 @@ public:
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
+ virtual void directional_shadow_atlas_set_size(int p_size) = 0;
virtual int get_directional_light_shadow_size(RID p_light_intance) = 0;
virtual void set_directional_shadow_count(int p_count) = 0;
@@ -107,18 +108,11 @@ public:
Map<InstanceBase *, uint32_t> instances;
};
- struct InstanceCustomData {
-
- virtual ~InstanceCustomData() {}
- };
-
struct InstanceBase {
VS::InstanceType base_type;
RID base;
- InstanceCustomData *custom_data;
-
RID skeleton;
RID material_override;
@@ -201,7 +195,6 @@ public:
InstanceBase() :
dependency_item(this) {
- custom_data = nullptr;
base_type = VS::INSTANCE_NONE;
cast_shadows = VS::SHADOW_CASTING_SETTING_ON;
receive_shadows = true;
@@ -215,9 +208,6 @@ public:
}
virtual ~InstanceBase() {
- if (custom_data) {
- memdelete(custom_data);
- }
clear_dependencies();
}
};
@@ -228,16 +218,10 @@ 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_size) = 0;
- virtual void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) = 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 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 void reflection_probe_instance_begin_render(RID p_instance) = 0;
virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
virtual RID gi_probe_instance_create() = 0;
@@ -245,21 +229,13 @@ 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_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_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;
virtual void set_time(double p_time) = 0;
virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) = 0;
- virtual void instance_create_custom_data(InstanceBase *p_instance) = 0;
- virtual void instance_free_custom_data(InstanceBase *p_instance) = 0;
- virtual void instance_custom_data_update_lights(InstanceBase *p_instance) = 0;
- virtual void instance_custom_data_update_reflection_probes(InstanceBase *p_instance) = 0;
- virtual void instance_custom_data_update_gi_probes(InstanceBase *p_instance) = 0;
- virtual void instance_custom_data_update_lightmap(InstanceBase *p_instance) = 0;
- virtual void instance_custom_data_update_transform(InstanceBase *p_instance) = 0;
-
virtual RID render_buffers_create() = 0;
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0;
@@ -442,7 +418,6 @@ public:
virtual void light_set_use_gi(RID p_light, bool p_enable) = 0;
virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) = 0;
- virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) = 0;
virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) = 0;
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp
index bf2214752d..1dc0503027 100644
--- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp
@@ -2375,7 +2375,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
attachments.push_back(af_color);
RD::AttachmentFormat af_depth;
- af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT;
+ af_depth.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;
af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
attachments.push_back(af_depth);
diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
index 11158db56f..1e32594118 100644
--- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -39,7 +39,23 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture) {
return uniform_set;
}
-void RasterizerEffectsRD::copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
+void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y) {
+
+ zeromem(&blur.push_constant, sizeof(BlurPushConstant));
+ if (p_flip_y) {
+ blur.push_constant.flags |= BLUR_FLAG_FLIP_Y;
+ }
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, Vector<Color>(), p_rect);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void RasterizerEffectsRD::region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
@@ -164,6 +180,23 @@ void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_frameb
RD::get_singleton()->draw_list_end();
}
+void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) {
+
+ CopyToDPPushConstant push_constant;
+ push_constant.bias = p_bias;
+ push_constant.z_far = p_z_far;
+ push_constant.z_near = p_z_near;
+ push_constant.z_flip = p_dp_flip;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, Vector<Color>(), p_rect);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy.pipelines[COPY_MODE_CUBE_TO_DP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
zeromem(&tonemap.push_constant, sizeof(TonemapPushConstant));
@@ -277,6 +310,20 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
}
}
+ {
+ // Initialize copier
+ Vector<String> copy_modes;
+ copy_modes.push_back("\n#define MODE_CUBE_TO_DP\n");
+
+ copy.shader.initialize(copy_modes);
+
+ copy.shader_version = copy.shader.version_create();
+
+ for (int i = 0; i < COPY_MODE_MAX; i++) {
+ copy.pipelines[i].setup(copy.shader.version_get_shader(copy.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+ }
+
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
index 5b54ddc18d..8249f0aff1 100644
--- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h
@@ -4,6 +4,7 @@
#include "core/math/camera_matrix.h"
#include "render_pipeline_vertex_format_cache_rd.h"
#include "servers/visual/rasterizer_rd/shaders/blur.glsl.gen.h"
+#include "servers/visual/rasterizer_rd/shaders/copy.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/tonemap.glsl.gen.h"
@@ -36,7 +37,8 @@ class RasterizerEffectsRD {
BLUR_FLAG_USE_BLUR_SECTION = (1 << 1),
BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
- BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4)
+ BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4),
+ BLUR_FLAG_FLIP_Y = (1 << 5)
};
struct BlurPushConstant {
@@ -146,6 +148,25 @@ class RasterizerEffectsRD {
RenderPipelineVertexFormatCacheRD pipelines[TONEMAP_MODE_MAX];
} tonemap;
+ struct CopyToDPPushConstant {
+ float bias;
+ float z_far;
+ float z_near;
+ uint32_t z_flip;
+ };
+
+ enum CopyMode {
+ COPY_MODE_CUBE_TO_DP,
+ COPY_MODE_MAX
+ };
+
+ struct Copy {
+
+ CopyShaderRD shader;
+ RID shader_version;
+ RenderPipelineVertexFormatCacheRD pipelines[COPY_MODE_MAX];
+ } copy;
+
RID default_sampler;
RID index_buffer;
RID index_array;
@@ -155,11 +176,13 @@ class RasterizerEffectsRD {
RID _get_uniform_set_from_texture(RID p_texture);
public:
- void copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
+ void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
+ void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false);
void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
void cubemap_roughness(RID p_source_rd_texture, bool p_source_is_panorama, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness);
void render_panorama(RD::DrawListID p_list, RenderingDevice::FramebufferFormatID p_fb_format, RID p_panorama, const CameraMatrix &p_camera, const Basis &p_orientation, float p_alpha, float p_multipler);
void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
+ void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
struct TonemapSettings {
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
index d8d1f5ec5d..41e04ad203 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
@@ -67,6 +67,18 @@ static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_
p_array[11] = 0;
}
+static _FORCE_INLINE_ void store_transform_3x3_430(const Transform &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.elements[0][0];
+ p_array[1] = p_mtx.basis.elements[1][0];
+ p_array[2] = p_mtx.basis.elements[2][0];
+ p_array[3] = p_mtx.basis.elements[0][1];
+ p_array[4] = p_mtx.basis.elements[1][1];
+ p_array[5] = p_mtx.basis.elements[2][1];
+ p_array[6] = p_mtx.basis.elements[0][2];
+ p_array[7] = p_mtx.basis.elements[1][2];
+ p_array[8] = p_mtx.basis.elements[2][2];
+}
+
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
@@ -296,8 +308,8 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
if (depth_draw == DEPTH_DRAW_OPAQUE) {
depth_stencil.enable_depth_write = false; //alpha does not draw depth
}
- } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS)) {
- if (k == SHADER_VERSION_DEPTH_PASS) {
+ } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS)) {
+ if (k == SHADER_VERSION_DEPTH_PASS || k == k == SHADER_VERSION_DEPTH_PASS_DP) {
//none, blend state contains nothing
} else {
blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
@@ -310,7 +322,7 @@ void RasterizerSceneForwardRD::ShaderData::set_code(const String &p_code) {
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
blend_state = blend_state_opaque;
- } else if (k == SHADER_VERSION_DEPTH_PASS) {
+ } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
//none, leave empty
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
blend_state = blend_state_opaque; //writes to normal and roughness in opaque way
@@ -583,60 +595,62 @@ bool RasterizerSceneForwardRD::free(RID p_rid) {
}
return false;
}
-/// INSTANCE DATA ///
-
-void RasterizerSceneForwardRD::instance_create_custom_data(InstanceBase *p_instance) {
- InstanceGeometryData *geom_data = memnew(InstanceGeometryData);
- geom_data->ubo = RD::get_singleton()->uniform_buffer_create(sizeof(InstanceGeometryData::UBO));
- geom_data->using_lightmap_gi = p_instance->lightmap.is_valid();
- p_instance->custom_data = geom_data;
-}
-void RasterizerSceneForwardRD::instance_free_custom_data(InstanceBase *p_instance) {
- InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
- ERR_FAIL_COND(!geom_data);
- RD::get_singleton()->free(geom_data->ubo);
- //uniform sets are freed as dependencies
- memdelete(geom_data);
- p_instance->custom_data = nullptr;
-}
+void RasterizerSceneForwardRD::_fill_instances(RenderList::Element **p_elements, int p_element_count) {
-void RasterizerSceneForwardRD::instance_custom_data_update_lights(InstanceBase *p_instance) {
- //unused
-}
-
-void RasterizerSceneForwardRD::instance_custom_data_update_reflection_probes(InstanceBase *p_instance) {
- //unused
-}
-void RasterizerSceneForwardRD::instance_custom_data_update_lightmap(InstanceBase *p_instance) {
- InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
- ERR_FAIL_COND(!geom_data);
+ for (int i = 0; i < p_element_count; i++) {
- geom_data->using_lightmap_gi = p_instance->lightmap.is_valid();
+ const RenderList::Element *e = p_elements[i];
+ InstanceData &id = scene_state.instances[i];
+ store_transform(e->instance->transform, id.transform);
+ store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
+ id.flags = 0;
+ id.mask = e->instance->layer_mask;
+
+ //forward
+
+ uint32_t reflection_count = 0;
+ uint32_t omni_count = 0;
+ uint32_t spot_count = 0;
+ uint32_t decal_count = 0;
+
+ if (!e->instance->light_instances.empty()) {
+ uint32_t light_count = e->instance->light_instances.size();
+ const RID *light_ptrs = e->instance->light_instances.ptr();
+
+ for (uint32_t j = 0; j < light_count; j++) {
+ if (render_pass != light_instance_get_render_pass(light_ptrs[j])) {
+ continue; //not rendered this frame
+ }
- if (geom_data->uniform_set_gi.is_valid() && RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
- RD::get_singleton()->free(geom_data->uniform_set_gi);
- }
- geom_data->uniform_set_gi = RID();
-}
+ RID base = light_instance_get_base_light(light_ptrs[j]);
-void RasterizerSceneForwardRD::instance_custom_data_update_gi_probes(InstanceBase *p_instance) {
- InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
- ERR_FAIL_COND(!geom_data);
+ uint32_t mask = storage->light_get_cull_mask(base);
+ if (!(mask & id.mask)) {
+ continue; //masked
+ }
- geom_data->using_vct_gi = p_instance->gi_probe_instances.size();
+ if (storage->light_get_type(base) == VS::LIGHT_OMNI) {
+ if (omni_count < 8) {
+ id.omni_light_indices[omni_count] = light_instance_get_index(light_ptrs[j]);
+ omni_count++;
+ }
+ } else {
+ if (spot_count < 8) {
+ id.omni_light_indices[spot_count] = light_instance_get_index(light_ptrs[j]);
+ spot_count++;
+ }
+ }
+ }
+ }
- if (geom_data->uniform_set_gi.is_valid() && RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
- RD::get_singleton()->free(geom_data->uniform_set_gi);
+ id.flags |= reflection_count;
+ id.flags |= omni_count << 3;
+ id.flags |= spot_count << 6;
+ id.flags |= decal_count << 9;
}
- geom_data->uniform_set_gi = RID();
-}
-
-void RasterizerSceneForwardRD::instance_custom_data_update_transform(InstanceBase *p_instance) {
- InstanceGeometryData *geom_data = (InstanceGeometryData *)p_instance->custom_data;
- ERR_FAIL_COND(!geom_data);
- geom_data->ubo_dirty = true;
+ RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true);
}
/// RENDERING ///
@@ -669,7 +683,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
//find cull variant
ShaderData::CullVariant cull_variant;
- if (p_pass_mode == PASS_MODE_SHADOW && e->instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
+ if ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) {
cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
} else {
bool mirror = e->instance->mirror;
@@ -700,59 +714,42 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
}
}
- InstanceGeometryData *geom_data = (InstanceGeometryData *)e->instance->custom_data;
-
ShaderVersion shader_version;
- RID instance_uniform_set;
switch (p_pass_mode) {
case PASS_MODE_COLOR:
case PASS_MODE_COLOR_TRANSPARENT: {
- if (p_no_gi) {
- instance_uniform_set = geom_data->uniform_set_base;
- shader_version = SHADER_VERSION_COLOR_PASS;
- } else if (geom_data->using_lightmap_gi) {
- instance_uniform_set = geom_data->uniform_set_gi;
+ if (e->uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS;
- } else if (geom_data->using_vct_gi) {
- instance_uniform_set = geom_data->uniform_set_gi;
+ } else if (e->uses_vct) {
shader_version = SHADER_VERSION_VCT_COLOR_PASS;
} else {
- instance_uniform_set = geom_data->uniform_set_gi;
shader_version = SHADER_VERSION_COLOR_PASS;
}
+
} break;
case PASS_MODE_COLOR_SPECULAR: {
- if (p_no_gi) {
- instance_uniform_set = geom_data->uniform_set_base;
- shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
- } else if (geom_data->using_lightmap_gi) {
- instance_uniform_set = geom_data->uniform_set_gi;
+ if (e->uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
- } else if (geom_data->using_vct_gi) {
- instance_uniform_set = geom_data->uniform_set_gi;
+ } else if (e->uses_vct) {
shader_version = SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR;
} else {
- instance_uniform_set = geom_data->uniform_set_gi;
shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
}
} break;
- case PASS_MODE_SHADOW: {
- shader_version = SHADER_VERSION_DEPTH_PASS;
- instance_uniform_set = geom_data->uniform_set_base;
- } break;
+ case PASS_MODE_SHADOW:
case PASS_MODE_DEPTH: {
shader_version = SHADER_VERSION_DEPTH_PASS;
- instance_uniform_set = geom_data->uniform_set_base;
+ } break;
+ case PASS_MODE_SHADOW_DP: {
+ shader_version = SHADER_VERSION_DEPTH_PASS_DP;
} break;
case PASS_MODE_DEPTH_NORMAL: {
shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL;
- instance_uniform_set = geom_data->uniform_set_base;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
- instance_uniform_set = geom_data->uniform_set_base;
} break;
}
@@ -812,8 +809,7 @@ void RasterizerSceneForwardRD::_render_list(RenderingDevice::DrawListID p_draw_l
prev_material = material;
}
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, instance_uniform_set, 3);
-
+ push_constant.index = i;
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant));
switch (e->instance->base_type) {
@@ -836,10 +832,13 @@ 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) {
+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) {
- CameraMatrix projection = p_cam_projection;
- projection.flip_y(); // Vulkan and modern APIs use Y-Down
+ //CameraMatrix projection = p_cam_projection;
+ //projection.flip_y(); // Vulkan and modern APIs use Y-Down
+ CameraMatrix correction;
+ correction.set_depth_correction();
+ CameraMatrix projection = correction * p_cam_projection;
//store camera into ubo
store_camera(projection, scene_state.ubo.projection_matrix);
@@ -847,6 +846,19 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
store_transform(p_cam_transform, scene_state.ubo.camera_matrix);
store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix);
+ scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
+ scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
+
+ if (p_shadow_atlas.is_valid()) {
+ Vector2 sas = shadow_atlas_get_size(p_shadow_atlas);
+ scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x;
+ scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y;
+ }
+ {
+ Vector2 dss = directional_shadow_get_size();
+ scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x;
+ scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y;
+ }
//time global variables
scene_state.ubo.time = time;
@@ -863,7 +875,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
//ambient
if (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && (env_bg == VS::ENV_BG_CLEAR_COLOR || env_bg == VS::ENV_BG_COLOR)) {
- Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? storage->render_target_get_clear_request_color(p_render_target) : environment_get_bg_color(p_environment);
+ Color color = (p_render_target.is_valid() && env_bg == VS::ENV_BG_CLEAR_COLOR) ? (p_render_target.is_valid() ? storage->render_target_get_clear_request_color(p_render_target) : Color(0, 0, 0)) : environment_get_bg_color(p_environment);
color = color.to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
@@ -1024,7 +1036,7 @@ void RasterizerSceneForwardRD::_setup_environment(RID p_render_target, RID p_env
RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
}
-void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode) {
+void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
@@ -1047,18 +1059,18 @@ void RasterizerSceneForwardRD::_add_geometry(InstanceBase *p_instance, uint32_t
ERR_FAIL_COND(!material);
- _add_geometry_with_material(p_instance, p_surface, material, p_pass_mode);
+ _add_geometry_with_material(p_instance, p_surface, material, p_pass_mode, p_geometry_index);
while (material->next_pass.is_valid()) {
material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D);
if (!material || !material->shader_data->valid)
break;
- _add_geometry_with_material(p_instance, p_surface, material, p_pass_mode);
+ _add_geometry_with_material(p_instance, p_surface, material, p_pass_mode, p_geometry_index);
}
}
-void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode) {
+void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode, uint32_t p_geometry_index) {
bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha);
@@ -1120,8 +1132,11 @@ void RasterizerSceneForwardRD::_add_geometry_with_material(InstanceBase *p_insta
e->material->shader_data->index = scene_state.current_shader_index++;
}
}
-
+ e->geometry_index = p_geometry_index;
e->material_index = e->material->index;
+ e->uses_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH;
+ e->uses_lightmap = e->instance->lightmap.is_valid();
+ e->uses_vct = e->instance->gi_probe_instances.size();
e->shader_index = e->shader_index;
e->depth_layer = e->instance->depth_layer;
e->priority = p_material->priority;
@@ -1140,89 +1155,14 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i
scene_state.used_normal_texture = false;
scene_state.used_depth_texture = false;
+ uint32_t geometry_index = 0;
+
//fill list
for (int i = 0; i < p_cull_count; i++) {
InstanceBase *inst = p_cull_result[i];
- InstanceGeometryData *geom_data = (InstanceGeometryData *)inst->custom_data;
-
- ERR_CONTINUE(!geom_data);
-
- if (geom_data->ubo_dirty) {
- //ubo marked dirty, must be updated
- InstanceGeometryData::UBO ubo;
- store_transform(inst->transform, ubo.transform);
- store_transform_3x3(inst->transform.basis.inverse().transposed(), ubo.normal_transform);
- ubo.flags = 0;
- ubo.pad[0] = 0;
- ubo.pad[1] = 0;
- ubo.pad[2] = 0;
- RD::get_singleton()->buffer_update(geom_data->ubo, 0, sizeof(InstanceGeometryData::UBO), &ubo, true);
- }
-
- if (p_no_gi) {
- if (geom_data->uniform_set_base.is_null() || !RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_base)) {
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(geom_data->ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
- u.binding = 1;
- u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
- uniforms.push_back(u);
- }
-
- geom_data->uniform_set_base = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 3);
- }
- } else {
- if (geom_data->uniform_set_gi.is_null() || !RD::get_singleton()->uniform_set_is_valid(geom_data->uniform_set_gi)) {
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.ids.push_back(geom_data->ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER;
- u.binding = 1;
- u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER));
- uniforms.push_back(u);
- }
-
- if (geom_data->using_lightmap_gi) {
- {
- RD::Uniform u;
- u.type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
-#ifndef _MSC_VER
-#warning Need to put actual lightmap or lightmap capture texture if exists
-#endif
- u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
- uniforms.push_back(u);
- }
- } else if (geom_data->using_vct_gi) {
-#ifndef _MSC_VER
-#warning Need to put actual vct textures here
-#endif
- }
-
- geom_data->uniform_set_gi = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 3);
- }
- }
-
//add geometry for drawing
switch (inst->base_type) {
@@ -1242,7 +1182,8 @@ void RasterizerSceneForwardRD::_fill_render_list(InstanceBase **p_cull_result, i
RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
- _add_geometry(inst, j, material, p_pass_mode);
+ uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index);
+ _add_geometry(inst, j, material, p_pass_mode, surface_index);
}
//mesh->last_pass=frame;
@@ -1341,11 +1282,207 @@ void RasterizerSceneForwardRD::_draw_sky(RD::DrawListID p_draw_list, RD::Framebu
storage->get_effects()->render_panorama(p_draw_list, p_fb_format, panorama, camera, sky_transform, 1.0, multiplier);
}
-void RasterizerSceneForwardRD::_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) {
+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) {
- RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
+ for (uint32_t i = 0; i < p_reflection_probe_cull_count; i++) {
+
+ RID rpi = p_reflection_probe_cull_result[i];
+
+ if (i >= scene_state.max_reflections) {
+ reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
+ continue;
+ }
+
+ reflection_probe_instance_set_render_index(rpi, i);
+
+ RID base_probe = reflection_probe_instance_get_probe(rpi);
+
+ ReflectionData &reflection_ubo = scene_state.reflections[i];
+
+ Vector3 extents = storage->reflection_probe_get_extents(base_probe);
+
+ 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;
+
+ 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;
+
+ float intensity = storage->reflection_probe_get_intensity(base_probe);
+ bool interior = storage->reflection_probe_is_interior(base_probe);
+ bool box_projection = storage->reflection_probe_is_box_projection(base_probe);
+
+ reflection_ubo.params[0] = intensity;
+ reflection_ubo.params[1] = 0;
+ reflection_ubo.params[2] = interior ? 1.0 : 0.0;
+ reflection_ubo.params[3] = box_projection ? 1.0 : 0.0;
+
+ if (interior) {
+ Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear();
+ float interior_ambient_energy = storage->reflection_probe_get_interior_ambient_energy(base_probe);
+ float interior_ambient_probe_contrib = storage->reflection_probe_get_interior_ambient_probe_contribution(base_probe);
+ reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
+ reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
+ reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
+ reflection_ubo.ambient[3] = interior_ambient_probe_contrib;
+ } else {
+ Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear();
+ if (is_environment(p_environment)) {
+ Color env_ambient_color = environment_get_ambient_light_color(p_environment).to_linear();
+ float env_ambient_energy = environment_get_ambient_light_ambient_energy(p_environment);
+ ambient_linear = env_ambient_color;
+ ambient_linear.r *= env_ambient_energy;
+ ambient_linear.g *= env_ambient_energy;
+ ambient_linear.b *= env_ambient_energy;
+ }
+
+ reflection_ubo.ambient[0] = ambient_linear.r;
+ reflection_ubo.ambient[1] = ambient_linear.g;
+ reflection_ubo.ambient[2] = ambient_linear.b;
+ reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light
+ }
+
+ Transform transform = reflection_probe_instance_get_transform(rpi);
+ Transform proj = (p_camera_inverse_transform * transform).inverse();
+ store_transform(proj, reflection_ubo.local_matrix);
+ }
+
+ if (p_reflection_probe_cull_count) {
+ RD::get_singleton()->buffer_update(scene_state.reflection_buffer, 0, MIN(scene_state.max_reflections, p_reflection_probe_cull_count) * sizeof(ReflectionData), scene_state.reflections, true);
+ }
+}
+
+void RasterizerSceneForwardRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas) {
+
+ uint32_t light_count = 0;
+ scene_state.ubo.directional_light_count = 0;
+
+ for (int i = 0; i < p_light_cull_count; i++) {
+
+ RID li = p_light_cull_result[i];
+ RID base = light_instance_get_base_light(li);
+
+ ERR_CONTINUE(base.is_null());
+
+ VS::LightType type = storage->light_get_type(base);
+ switch (type) {
+
+ case VS::LIGHT_DIRECTIONAL: {
+
+ if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) {
+ continue;
+ }
+ } break;
+ case VS::LIGHT_SPOT:
+ case VS::LIGHT_OMNI: {
+
+ if (light_count >= scene_state.max_lights) {
+ continue;
+ }
+
+ Transform light_transform = light_instance_get_base_transform(li);
+
+ LightData &light_data = scene_state.lights[light_count];
+
+ float sign = storage->light_is_negative(base) ? -1 : 1;
+ Color linear_col = storage->light_get_color(base).to_linear();
+
+ light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, VS::LIGHT_PARAM_ATTENUATION));
+ light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, VS::LIGHT_PARAM_ENERGY) * Math_PI);
+
+ light_data.color_specular[0] = CLAMP(uint32_t(linear_col.r * 255), 0, 255);
+ light_data.color_specular[1] = CLAMP(uint32_t(linear_col.g * 255), 0, 255);
+ light_data.color_specular[2] = CLAMP(uint32_t(linear_col.b * 255), 0, 255);
+ light_data.color_specular[3] = CLAMP(uint32_t(storage->light_get_param(base, VS::LIGHT_PARAM_SPECULAR) * 255), 0, 255);
+
+ light_data.inv_radius = 1.0 / MAX(0.001, storage->light_get_param(base, VS::LIGHT_PARAM_RANGE));
+
+ Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin);
+
+ light_data.position[0] = pos.x;
+ light_data.position[1] = pos.y;
+ light_data.position[2] = pos.z;
+
+ Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized();
+
+ light_data.direction[0] = direction.x;
+ light_data.direction[1] = direction.y;
+ light_data.direction[2] = direction.z;
+
+ light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ATTENUATION));
+ light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ANGLE))));
+
+ light_data.mask = storage->light_get_cull_mask(base);
+
+ Color shadow_color = storage->light_get_shadow_color(base);
+
+ bool has_shadow = 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);
+ light_data.shadow_color_enabled[3] = has_shadow ? 255 : 0;
+
+ light_data.atlas_rect[0] = 0;
+ light_data.atlas_rect[1] = 0;
+ 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)) {
+ // fill in the shadow information
+
+ Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
+
+ if (type == VS::LIGHT_OMNI) {
+
+ light_data.atlas_rect[0] = rect.position.x;
+ light_data.atlas_rect[1] = rect.position.y;
+ light_data.atlas_rect[2] = rect.size.width;
+ light_data.atlas_rect[3] = rect.size.height * 0.5;
+
+ Transform proj = (p_camera_inverse_transform * light_transform).inverse();
+
+ store_transform(proj, light_data.shadow_matrix);
+ } else if (type == VS::LIGHT_SPOT) {
- ERR_FAIL_COND(!render_buffer); //bug out for now
+ Transform modelview = (p_camera_inverse_transform * light_transform).inverse();
+ CameraMatrix bias;
+ bias.set_light_bias();
+ CameraMatrix rectm;
+ rectm.set_light_atlas_rect(rect);
+
+ CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview;
+ store_camera(shadow_mtx, light_data.shadow_matrix);
+ }
+ }
+
+ light_instance_set_index(li, light_count);
+
+ light_count++;
+ } break;
+ }
+
+ light_instance_set_render_pass(li, render_pass);
+
+ //update UBO for forward rendering, blit to texture for clustered
+ }
+
+ if (light_count) {
+ RD::get_singleton()->buffer_update(scene_state.light_buffer, 0, sizeof(LightData) * light_count, scene_state.lights, true);
+ }
+
+ if (scene_state.ubo.directional_light_count) {
+ RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * light_count, scene_state.directional_lights, true);
+ }
+}
+
+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) {
+
+ RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)p_buffer_data;
//first of all, make a new render pass
render_pass++;
@@ -1388,14 +1525,34 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
scene_state.ubo.viewport_size[1] = vp_he.y;
RID render_target;
+ Size2 screen_pixel_size;
+ RID opaque_framebuffer;
+ RID alpha_framebuffer;
if (render_buffer) {
- scene_state.ubo.screen_pixel_size[0] = 1.0 / render_buffer->width;
- scene_state.ubo.screen_pixel_size[1] = 1.0 / render_buffer->height;
+ screen_pixel_size.width = 1.0 / render_buffer->width;
+ screen_pixel_size.height = 1.0 / render_buffer->height;
render_target = render_buffer->render_target;
+
+ opaque_framebuffer = render_buffer->color_fb;
+ alpha_framebuffer = opaque_framebuffer;
+
+ } else if (p_reflection_probe.is_valid()) {
+ uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe);
+ screen_pixel_size.width = 1.0 / resolution;
+ screen_pixel_size.height = 1.0 / resolution;
+
+ opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass);
+ alpha_framebuffer = opaque_framebuffer;
+
+ } else {
+ ERR_FAIL(); //bug?
}
- _setup_environment(render_target, p_environment, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid());
+ _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas);
+ _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);
+
#if 0
for (int i = 0; i < p_light_cull_count; i++) {
@@ -1771,10 +1928,12 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
}
}
- _setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap);
+ _setup_render_base_uniform_set(RID(), RID(), RID(), RID(), radiance_cubemap, p_shadow_atlas, RID());
render_list.sort_by_key(false);
+ _fill_instances(render_list.elements, render_list.element_count);
+
bool can_continue = true; //unless the middle buffers are needed
bool using_separate_specular = false;
@@ -1782,14 +1941,14 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
//regular forward for now
Vector<Color> c;
c.push_back(clear_color.to_linear());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, keep_color ? RD::INITIAL_ACTION_KEEP_COLOR : RD::INITIAL_ACTION_CLEAR, (can_continue || draw_sky) ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP_COLOR : RD::INITIAL_ACTION_CLEAR, (can_continue || draw_sky) ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
RD::get_singleton()->draw_list_end();
}
if (draw_sky) {
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
- _draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), p_environment, p_cam_projection, p_cam_transform, 1.0);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
+ _draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), p_environment, p_cam_projection, p_cam_transform, 1.0);
RD::get_singleton()->draw_list_end();
if (using_separate_specular && !can_continue) {
@@ -1887,9 +2046,11 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
#endif
render_list.sort_by_reverse_depth_and_priority(true);
+ _fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count);
+
{
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(render_buffer->color_fb, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP_COLOR_AND_DEPTH, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(render_buffer->color_fb), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP_COLOR_AND_DEPTH, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr);
RD::get_singleton()->draw_list_end();
}
@@ -1907,7 +2068,7 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
}
#endif
if (p_reflection_probe.is_valid()) {
- //rendering a probe, do no more!
+ //was rendering a probe, so do no more
return;
}
@@ -1931,6 +2092,15 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
storage->render_target_disable_clear_request(render_buffer->render_target);
+ if (true) {
+ if (p_shadow_atlas.is_valid()) {
+ RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
+ Size2 rtsize = storage->render_target_get_size(render_buffer->render_target);
+
+ effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(render_buffer->render_target), Rect2(Vector2(), rtsize / 2));
+ }
+ }
+
#if 0
_post_process(env, p_cam_projection);
// Needed only for debugging
@@ -1988,8 +2158,38 @@ void RasterizerSceneForwardRD::_render_scene(RenderBufferData *p_buffer_data, co
//disable all stuff
#endif
}
+void RasterizerSceneForwardRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip) {
-void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap) {
+ render_pass++;
+
+ scene_state.ubo.shadow_z_offset = p_bias;
+ scene_state.ubo.shadow_z_slope_scale = p_normal_bias;
+ scene_state.ubo.z_far = p_zfar;
+ scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+
+ _setup_environment(RID(), RID(), p_projection, p_transform, true, Vector2(1, 1), RID());
+
+ render_list.clear();
+
+ PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
+
+ _fill_render_list(p_cull_result, p_cull_count, pass_mode, true);
+
+ _setup_render_base_uniform_set(RID(), RID(), RID(), RID(), RID(), RID(), RID());
+
+ render_list.sort_by_key(false);
+
+ _fill_instances(render_list.elements, render_list.element_count);
+
+ {
+ //regular forward for now
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true);
+ RD::get_singleton()->draw_list_end();
+ }
+}
+
+void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap, RID p_shadow_atlas, RID p_reflection_atlas) {
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
@@ -2065,20 +2265,79 @@ void RasterizerSceneForwardRD::_setup_render_base_uniform_set(RID p_depth_buffer
{
RD::Uniform u;
u.binding = 7;
+ u.type = RD::UNIFORM_TYPE_SAMPLER;
+ u.ids.push_back(shadow_sampler);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 8;
u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(scene_state.uniform_buffer);
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+ u.binding = 9;
+ u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(scene_state.instance_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 10;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(scene_state.reflection_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 11;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(scene_state.light_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 12;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ if (p_shadow_atlas.is_valid()) {
+ u.ids.push_back(shadow_atlas_get_texture(p_shadow_atlas));
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ }
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 13;
+ u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.ids.push_back(scene_state.directional_light_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 14;
+ u.type = RD::UNIFORM_TYPE_TEXTURE;
+ if (directional_shadow_get_texture().is_valid()) {
+ u.ids.push_back(directional_shadow_get_texture());
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ }
+ uniforms.push_back(u);
+ }
render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, 0);
}
RasterizerSceneForwardRD *RasterizerSceneForwardRD::singleton = NULL;
-void RasterizerSceneForwardRD::set_scene_pass(uint64_t p_pass) {
- scene_pass = p_pass;
-}
-
void RasterizerSceneForwardRD::set_time(double p_time) {
time = p_time;
}
@@ -2097,8 +2356,53 @@ 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
+ uint32_t reflection_buffer_size;
+ if (uniform_max_size < 65536) {
+ //Yes, you guessed right, ARM again
+ reflection_buffer_size = uniform_max_size;
+ } else {
+ reflection_buffer_size = 65536;
+ }
+
+ scene_state.max_reflections = reflection_buffer_size / sizeof(ReflectionData);
+ scene_state.reflections = memnew_arr(ReflectionData, scene_state.max_reflections);
+ scene_state.reflection_buffer = RD::get_singleton()->uniform_buffer_create(reflection_buffer_size);
+ defines += "\n#define MAX_REFLECTION_DATA_STRUCTS " + itos(scene_state.max_reflections) + "\n";
+ }
+
+ { //lights
+ scene_state.max_lights = MIN(65536, uniform_max_size) / sizeof(LightData);
+ uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData);
+ print_line("ID: " + itos(sizeof(InstanceData)));
+ scene_state.lights = memnew_arr(LightData, scene_state.max_lights);
+ scene_state.light_buffer = RD::get_singleton()->uniform_buffer_create(light_buffer_size);
+ defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n";
+
+ scene_state.max_directional_lights = 4;
+ uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData);
+ scene_state.directional_lights = memnew_arr(DirectionalLightData, scene_state.max_directional_lights);
+ scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
+ defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(scene_state.max_directional_lights) + "\n";
+ }
+
Vector<String> shader_versions;
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n");
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n");
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_BUFFER\n");
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define ENABLE_WRITE_NORMAL_ROUGHNESS_BUFFER\n");
shader_versions.push_back("");
@@ -2198,7 +2502,7 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
- actions.usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n";
+ actions.usage_defines["TRANSMISSION"] = "#define LIGHT_TRANSMISSION_USED\n";
actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
@@ -2249,11 +2553,17 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
}
//render list
- render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)256000);
+ render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000);
render_list.init();
- scene_pass = 0;
render_pass = 0;
+ {
+
+ scene_state.max_instances = render_list.max_elements;
+ scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances);
+ scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances);
+ }
+
scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
{
@@ -2266,6 +2576,16 @@ RasterizerSceneForwardRD::RasterizerSceneForwardRD(RasterizerStorageRD *p_storag
MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D);
default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
}
+
+ {
+
+ RD::SamplerState sampler;
+ sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler.enable_compare = true;
+ sampler.compare_op = RD::COMPARE_OP_LESS;
+ shadow_sampler = RD::get_singleton()->sampler_create(sampler);
+ }
}
RasterizerSceneForwardRD::~RasterizerSceneForwardRD() {
@@ -2273,4 +2593,9 @@ RasterizerSceneForwardRD::~RasterizerSceneForwardRD() {
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
+
+ {
+ RD::get_singleton()->free(scene_state.reflection_buffer);
+ memdelete_arr(scene_state.reflections);
+ }
}
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
index ca28678fcc..f7d0e419ad 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
@@ -42,6 +42,7 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
+ SHADER_VERSION_DEPTH_PASS_DP,
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL,
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
SHADER_VERSION_COLOR_PASS,
@@ -174,37 +175,11 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
return static_cast<RasterizerSceneForwardRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
- /* Instance Custom Data */
-
- struct InstanceGeometryData : public InstanceCustomData {
-
- struct UBO {
- float transform[16];
- float normal_transform[12];
- uint32_t flags;
- uint32_t pad[3];
- };
-
- RID ubo;
- RID uniform_set_base;
- RID uniform_set_gi;
-
- bool ubo_dirty = true;
- bool using_lightmap_gi = false;
- bool using_vct_gi = false;
- };
-
/* Push Constant */
struct PushConstant {
- uint32_t reflection_probe_count;
- uint32_t omni_light_count;
- uint32_t spot_light_count;
- uint32_t decal_count;
- float reflection_probe_indices[4];
- float omni_light_indices[4];
- float spot_light_indices[4];
- float decal_indices[4];
+ uint32_t index;
+ uint32_t pad[3];
};
/* Framebuffer */
@@ -227,11 +202,65 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
virtual RenderBufferData *_create_render_buffer_data();
+ RID shadow_sampler;
RID render_base_uniform_set;
- void _setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap);
+ void _setup_render_base_uniform_set(RID p_depth_buffer, RID p_color_buffer, RID p_normal_buffer, RID p_roughness_limit_buffer, RID p_radiance_cubemap, RID p_shadow_atlas, RID p_reflection_atlas);
/* Scene State UBO */
+ struct ReflectionData { //should always be 128 bytes
+ float box_extents[4];
+ float box_offset[4];
+ 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
+ };
+
+ struct LightData {
+ float position[3];
+ float inv_radius;
+ float direction[3];
+ uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
+ uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
+ uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
+ uint32_t mask;
+ uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
+ float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
+ float shadow_matrix[16];
+ };
+
+ struct DirectionalLightData {
+
+ float direction[3];
+ float energy;
+ float color[3];
+ float specular;
+ uint32_t mask;
+ uint32_t pad[3];
+ float shadow_color[3];
+ uint32_t shadow_enabled;
+ float shadow_atlas_rect[4];
+ float shadow_split_offsets[4];
+ float shadow_matrix1[16];
+ float shadow_matrix2[16];
+ float shadow_matrix3[16];
+ float shadow_matrix4[16];
+ };
+
+ struct InstanceData {
+ float transform[16];
+ float normal_transform[16];
+ uint32_t flags;
+ uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer
+ uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
+ uint32_t mask;
+
+ uint16_t reflection_probe_indices[8];
+ uint16_t omni_light_indices[8];
+ uint16_t spot_light_indices[8];
+ uint16_t decal_indices[8];
+ };
+
struct SceneState {
struct UBO {
float projection_matrix[16];
@@ -257,12 +286,37 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
uint32_t use_reflection_cubemap;
float radiance_inverse_xform[12];
+
+ float shadow_atlas_pixel_size[2];
+ float directional_shadow_pixel_size[2];
+
+ uint32_t directional_light_count;
+ float dual_paraboloid_side;
+ float z_far;
+ uint32_t pad[1];
};
UBO ubo;
RID uniform_buffer;
+ ReflectionData *reflections;
+ uint32_t max_reflections;
+ RID reflection_buffer;
+ uint32_t max_reflection_probes_per_instance;
+
+ LightData *lights;
+ uint32_t max_lights;
+ RID light_buffer;
+
+ DirectionalLightData *directional_lights;
+ uint32_t max_directional_lights;
+ RID directional_light_buffer;
+
+ RID instance_buffer;
+ InstanceData *instances;
+ uint32_t max_instances;
+
bool used_screen_texture = false;
bool used_normal_texture = false;
bool used_depth_texture = false;
@@ -283,10 +337,14 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
union {
struct {
//from least significant to most significant in sort, TODO: should be endian swapped on big endian
- uint64_t material_index : 20;
- uint64_t shader_index : 20;
- uint64_t priority : 16;
- uint64_t depth_layer : 8;
+ uint64_t geometry_index : 20;
+ uint64_t material_index : 15;
+ uint64_t shader_index : 12;
+ uint64_t uses_instancing : 1;
+ uint64_t uses_vct : 1;
+ uint64_t uses_lightmap : 1;
+ uint64_t depth_layer : 4;
+ uint64_t priority : 8;
};
uint64_t sort_key;
@@ -407,7 +465,6 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
RenderList render_list;
static RasterizerSceneForwardRD *singleton;
- uint64_t scene_pass;
uint64_t render_pass;
double time;
RID default_shader;
@@ -419,39 +476,33 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
PASS_MODE_COLOR_SPECULAR,
PASS_MODE_COLOR_TRANSPARENT,
PASS_MODE_SHADOW,
+ PASS_MODE_SHADOW_DP,
PASS_MODE_DEPTH,
PASS_MODE_DEPTH_NORMAL,
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);
+ 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_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);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi);
- _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode);
- _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode);
+ _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index);
+ _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, PassMode p_pass_mode, uint32_t p_geometry_index);
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
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_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_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:
- virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {}
-
- virtual void set_scene_pass(uint64_t p_pass);
virtual void set_time(double p_time);
virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {}
- virtual void instance_create_custom_data(InstanceBase *p_instance);
- virtual void instance_free_custom_data(InstanceBase *p_instance);
- virtual void instance_custom_data_update_lights(InstanceBase *p_instance);
- virtual void instance_custom_data_update_reflection_probes(InstanceBase *p_instance);
- virtual void instance_custom_data_update_gi_probes(InstanceBase *p_instance);
- virtual void instance_custom_data_update_lightmap(InstanceBase *p_instance);
- virtual void instance_custom_data_update_transform(InstanceBase *p_instance);
-
virtual bool free(RID p_rid);
RasterizerSceneForwardRD(RasterizerStorageRD *p_storage);
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
index 97e3f9cdb6..72000e824a 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp
@@ -1,6 +1,204 @@
#include "rasterizer_scene_rd.h"
+#include "core/os/os.h"
#include "core/project_settings.h"
+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();
+ }
+}
+
+void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, bool p_quality) {
+ //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);
+ }
+
+ 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());
+
+ for (int i = 0; i < roughness_layers; i++) {
+ ReflectionData::Layer layer;
+ uint32_t mmw = w;
+ uint32_t mmh = h;
+ layer.mipmaps.resize(mipmaps);
+ for (int j = 0; j < mipmaps; j++) {
+ ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j];
+ 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);
+ Vector<RID> fbtex;
+ fbtex.push_back(mm.views[k]);
+ mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
+ }
+
+ mmw = MAX(1, mmw >> 1);
+ mmh = MAX(1, mmh >> 1);
+ }
+
+ rd.layers.push_back(layer);
+ }
+
+ } 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;
+ layer.mipmaps.resize(roughness_layers);
+ for (int j = 0; j < roughness_layers; j++) {
+ ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j];
+ 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);
+ Vector<RID> fbtex;
+ fbtex.push_back(mm.views[k]);
+ mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
+ }
+
+ mmw = MAX(1, mmw >> 1);
+ mmh = MAX(1, mmh >> 1);
+ }
+
+ 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);
+}
+
+void RasterizerSceneRD::_create_reflection_from_panorama(ReflectionData &rd, RID p_panorama, bool p_quality) {
+
+ if (sky_use_cubemap_array) {
+
+ if (p_quality) {
+ //render directly to the layers
+ for (int i = 0; i < rd.layers.size(); i++) {
+ for (int j = 0; j < 6; j++) {
+ storage->get_effects()->cubemap_roughness(p_panorama, true, rd.layers[i].mipmaps[0].framebuffers[j], j, sky_ggx_samples_quality, float(i) / (rd.layers.size() - 1.0));
+ }
+ }
+ } else {
+ //render to first mipmap
+ for (int j = 0; j < 6; j++) {
+ storage->get_effects()->cubemap_roughness(p_panorama, true, rd.layers[0].mipmaps[0].framebuffers[j], j, sky_ggx_samples_realtime, 0.0);
+ }
+ //do the rest in other mipmaps and use cubemap itself as source
+ for (int i = 1; i < roughness_layers; i++) {
+ //render using a smaller mipmap, then copy to main layer
+ for (int j = 0; j < 6; j++) {
+ //storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, false, rd.layers[0].mipmaps[i].framebuffers[0], j, sky_ggx_samples_realtime, float(i) / (rd.layers.size() - 1.0));
+ storage->get_effects()->cubemap_roughness(p_panorama, true, rd.layers[0].mipmaps[i].framebuffers[0], j, sky_ggx_samples_realtime, float(i) / (rd.layers.size() - 1.0));
+ storage->get_effects()->region_copy(rd.layers[0].mipmaps[i].views[0], rd.layers[i].mipmaps[0].framebuffers[j], Rect2());
+ }
+ }
+ }
+ } else {
+
+ if (p_quality) {
+ //render directly to the layers
+ for (int i = 0; i < rd.layers[0].mipmaps.size(); i++) {
+ for (int j = 0; j < 6; j++) {
+ storage->get_effects()->cubemap_roughness(p_panorama, true, rd.layers[0].mipmaps[i].framebuffers[j], j, sky_ggx_samples_quality, float(i) / (rd.layers[0].mipmaps.size() - 1.0));
+ }
+ }
+ } else {
+
+ for (int j = 0; j < 6; j++) {
+ storage->get_effects()->cubemap_roughness(p_panorama, true, rd.layers[0].mipmaps[0].framebuffers[j], j, sky_ggx_samples_realtime, 0);
+ }
+
+ for (int i = 1; i < rd.layers[0].mipmaps.size(); i++) {
+ for (int j = 0; j < 6; j++) {
+ storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, false, rd.layers[0].mipmaps[i].framebuffers[j], j, sky_ggx_samples_realtime, float(i) / (rd.layers[0].mipmaps.size() - 1.0));
+ }
+ }
+ }
+ }
+}
+
+void RasterizerSceneRD::_create_reflection_from_base_mipmap(ReflectionData &rd, bool p_quality, int p_cube_side) {
+
+ if (sky_use_cubemap_array) {
+
+ if (p_quality) {
+ //render directly to the layers
+ for (int i = 1; i < rd.layers.size(); i++) {
+ storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, false, rd.layers[i].mipmaps[0].framebuffers[p_cube_side], p_cube_side, sky_ggx_samples_quality, float(i) / (rd.layers.size() - 1.0));
+ }
+ } else {
+ //do the rest in other mipmaps and use cubemap itself as source
+ for (int i = 1; i < roughness_layers; i++) {
+ //render using a smaller mipmap, then copy to main layer
+ storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, false, rd.layers[0].mipmaps[i].framebuffers[0], p_cube_side, sky_ggx_samples_realtime, float(i) / (rd.layers.size() - 1.0));
+ storage->get_effects()->region_copy(rd.layers[0].mipmaps[i].views[0], rd.layers[i].mipmaps[0].framebuffers[p_cube_side], Rect2());
+ }
+ }
+ } else {
+
+ if (p_quality) {
+ //render directly to the layers
+ for (int i = 1; i < rd.layers[0].mipmaps.size(); i++) {
+ storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, false, rd.layers[0].mipmaps[i].framebuffers[p_cube_side], p_cube_side, sky_ggx_samples_quality, float(i) / (rd.layers[0].mipmaps.size() - 1.0));
+ }
+ } else {
+
+ for (int i = 1; i < rd.layers[0].mipmaps.size(); i++) {
+ storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, false, rd.layers[0].mipmaps[i].framebuffers[p_cube_side], p_cube_side, sky_ggx_samples_realtime, float(i) / (rd.layers[0].mipmaps.size() - 1.0));
+ }
+ }
+ }
+}
+
+void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd, bool p_quality) {
+
+ if (sky_use_cubemap_array) {
+
+ for (int i = 0; i < rd.layers.size(); i++) {
+ for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) {
+ for (int k = 0; k < 6; k++) {
+ RID view = rd.layers[i].mipmaps[j].views[k];
+ RID fb = rd.layers[i].mipmaps[j + 1].framebuffers[k];
+ Vector2 size = rd.layers[i].mipmaps[j].size;
+ size = Vector2(1.0 / size.x, 1.0 / size.y);
+ storage->get_effects()->make_mipmap(view, fb, size);
+ }
+ }
+ }
+ }
+}
+
RID RasterizerSceneRD::sky_create() {
return sky_owner.make_rid(Sky());
}
@@ -22,14 +220,7 @@ 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()) {
- //if size changes, everything must be cleared
- RD::get_singleton()->free(sky->radiance);
- //everything else gets dependency, erase, so just clean it up
- sky->radiance = RID();
- sky->layers.clear();
- sky->radiance_base_cubemap = RID();
- }
+ _clear_reflection_data(sky->reflection);
}
void RasterizerSceneRD::sky_set_mode(RID p_sky, VS::SkyMode p_mode) {
@@ -51,8 +242,7 @@ void RasterizerSceneRD::sky_set_texture(RID p_sky, RID p_panorama) {
if (sky->panorama.is_valid()) {
sky->panorama = RID();
- RD::get_singleton()->free(sky->radiance);
- sky->radiance = RID();
+ _clear_reflection_data(sky->reflection);
}
sky->panorama = p_panorama;
@@ -70,155 +260,16 @@ void RasterizerSceneRD::_update_dirty_skys() {
//update sky configuration if texture is missing
- if (sky->radiance.is_null()) {
- //recreate radiance and all data
- int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1;
- if (sky->mode == VS::SKY_MODE_REALTIME) {
- //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());
-
- for (int i = 0; i < roughness_layers; i++) {
- Sky::Layer layer;
- uint32_t mmw = w;
- uint32_t mmh = h;
- layer.mipmaps.resize(mipmaps);
- for (int j = 0; j < mipmaps; j++) {
- Sky::Layer::Mipmap &mm = layer.mipmaps.write[j];
- 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(), sky->radiance, i * 6 + k, j);
- Vector<RID> fbtex;
- fbtex.push_back(mm.views[k]);
- mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
- }
-
- mmw = MAX(1, mmw >> 1);
- mmh = MAX(1, mmh >> 1);
- }
-
- sky->layers.push_back(layer);
- }
-
- } 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());
-
- Sky::Layer layer;
- uint32_t mmw = w;
- uint32_t mmh = h;
- layer.mipmaps.resize(roughness_layers);
- for (int j = 0; j < roughness_layers; j++) {
- Sky::Layer::Mipmap &mm = layer.mipmaps.write[j];
- 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(), sky->radiance, k, j);
- Vector<RID> fbtex;
- fbtex.push_back(mm.views[k]);
- mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
- }
-
- mmw = MAX(1, mmw >> 1);
- mmh = MAX(1, mmh >> 1);
- }
-
- sky->layers.push_back(layer);
- }
-
- sky->radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sky->radiance, 0, 0, RD::TEXTURE_SLICE_CUBEMAP);
+ if (sky->reflection.radiance.is_null()) {
+ _update_reflection_data(sky->reflection, sky->radiance_size, sky->mode == VS::SKY_MODE_QUALITY);
}
RID panorama_texture = storage->texture_get_rd_texture(sky->panorama);
if (panorama_texture.is_valid()) {
//is there a panorama texture?
-
- if (sky_use_cubemap_array) {
-
- if (sky->mode == VS::SKY_MODE_QUALITY) {
- //render directly to the layers
- for (int i = 0; i < sky->layers.size(); i++) {
- for (int j = 0; j < 6; j++) {
- storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[i].mipmaps[0].framebuffers[j], j, sky_ggx_samples_quality, float(i) / (sky->layers.size() - 1.0));
- }
- }
- } else if (sky->mode == VS::SKY_MODE_REALTIME) {
- //render to first mipmap
- for (int j = 0; j < 6; j++) {
- storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[0].mipmaps[0].framebuffers[j], j, sky_ggx_samples_realtime, 0.0);
- }
- //do the rest in other mipmaps and use cubemap itself as source
- for (int i = 1; i < roughness_layers; i++) {
- //render using a smaller mipmap, then copy to main layer
- for (int j = 0; j < 6; j++) {
- //storage->get_effects()->cubemap_roughness(sky->radiance_base_cubemap, false, sky->layers[0].mipmaps[i].framebuffers[0], j, sky_ggx_samples_realtime, float(i) / (sky->layers.size() - 1.0));
- storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[0].mipmaps[i].framebuffers[0], j, sky_ggx_samples_realtime, float(i) / (sky->layers.size() - 1.0));
- storage->get_effects()->copy(sky->layers[0].mipmaps[i].views[0], sky->layers[i].mipmaps[0].framebuffers[j], Rect2());
- }
- }
- }
-
- //generate mipmaps
-
- for (int i = 0; i < sky->layers.size(); i++) {
- for (int j = 0; j < sky->layers[i].mipmaps.size() - 1; j++) {
- for (int k = 0; k < 6; k++) {
- RID view = sky->layers[i].mipmaps[j].views[k];
- RID fb = sky->layers[i].mipmaps[j + 1].framebuffers[k];
- Vector2 size = sky->layers[i].mipmaps[j].size;
- size = Vector2(1.0 / size.x, 1.0 / size.y);
- storage->get_effects()->make_mipmap(view, fb, size);
- }
- }
- }
- } else {
-
- if (sky->mode == VS::SKY_MODE_QUALITY) {
- //render directly to the layers
- for (int i = 0; i < sky->layers[0].mipmaps.size(); i++) {
- for (int j = 0; j < 6; j++) {
- storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[0].mipmaps[i].framebuffers[j], j, sky_ggx_samples_quality, float(i) / (sky->layers[0].mipmaps.size() - 1.0));
- }
- }
- } else {
-
- for (int j = 0; j < 6; j++) {
- storage->get_effects()->cubemap_roughness(panorama_texture, true, sky->layers[0].mipmaps[0].framebuffers[j], j, sky_ggx_samples_realtime, 0);
- }
-
- for (int i = 1; i < sky->layers[0].mipmaps.size(); i++) {
- for (int j = 0; j < 6; j++) {
- storage->get_effects()->cubemap_roughness(sky->radiance_base_cubemap, false, sky->layers[0].mipmaps[i].framebuffers[j], j, sky_ggx_samples_realtime, float(i) / (sky->layers[0].mipmaps.size() - 1.0));
- }
- }
- }
- }
+ _create_reflection_from_panorama(sky->reflection, panorama_texture, sky->mode == VS::SKY_MODE_QUALITY);
+ _update_reflection_mipmaps(sky->reflection, sky->mode == VS::SKY_MODE_QUALITY);
}
Sky *next = sky->dirty_list;
@@ -244,7 +295,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->radiance;
+ return sky->reflection.radiance;
}
RID RasterizerSceneRD::environment_create() {
@@ -416,6 +467,593 @@ bool RasterizerSceneRD::is_environment(RID p_env) const {
return environment_owner.owns(p_env);
}
+////////////////////////////////////////////////////////////
+
+RID RasterizerSceneRD::reflection_probe_instance_create(RID p_probe) {
+ ReflectionProbeInstance rpi;
+ rpi.probe = p_probe;
+ return reflection_probe_instance_owner.make_rid(rpi);
+}
+
+void RasterizerSceneRD::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!rpi);
+
+ rpi->transform = p_transform;
+ rpi->dirty = true;
+}
+
+bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) {
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+
+ if (rpi->rendering) {
+ return false;
+ }
+
+ if (rpi->dirty) {
+ 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;
+}
+
+void RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance) {
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!rpi);
+ rpi->rendering = true;
+ rpi->processing_side = 0;
+
+ 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);
+
+ rpi->current_resolution = probe_resolution;
+
+ if (rpi->depth_buffer.is_valid()) {
+ RD::get_singleton()->free(rpi->depth_buffer);
+ }
+ {
+ 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;
+
+ rpi->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+
+ 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);
+ }
+ }
+}
+
+bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instance) {
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+ ERR_FAIL_COND_V(!rpi->rendering, false);
+
+ _create_reflection_from_base_mipmap(rpi->reflection, 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;
+ }
+}
+
+uint32_t RasterizerSceneRD::reflection_probe_instance_get_resolution(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, 0);
+
+ return rpi->current_resolution;
+}
+
+RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, RID());
+ ERR_FAIL_INDEX_V(p_index, 6, RID());
+
+ return rpi->render_fb[p_index];
+}
+
+///////////////////////////////////////////////////////////
+
+RID RasterizerSceneRD::shadow_atlas_create() {
+
+ return shadow_atlas_owner.make_rid(ShadowAtlas());
+}
+
+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);
+
+ if (p_size == shadow_atlas->size)
+ return;
+
+ // erasing atlas
+ if (shadow_atlas->depth.is_valid()) {
+ RD::get_singleton()->free(shadow_atlas->depth);
+ shadow_atlas->depth = RID();
+ shadow_atlas->fb = RID();
+ }
+ for (int i = 0; i < 4; i++) {
+ //clear subdivisions
+ shadow_atlas->quadrants[i].shadows.resize(0);
+ shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision);
+ }
+
+ //erase shadow atlas reference from lights
+ for (Map<RID, uint32_t>::Element *E = shadow_atlas->shadow_owners.front(); E; E = E->next()) {
+ LightInstance *li = light_instance_owner.getornull(E->key());
+ ERR_CONTINUE(!li);
+ li->shadow_atlases.erase(p_atlas);
+ }
+
+ //clear owners
+ shadow_atlas->shadow_owners.clear();
+
+ shadow_atlas->size = p_size;
+
+ if (shadow_atlas->size) {
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R32_SFLOAT;
+ tf.width = shadow_atlas->size;
+ tf.height = shadow_atlas->size;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ Vector<RID> fb;
+ fb.push_back(shadow_atlas->depth);
+ shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+}
+
+void RasterizerSceneRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
+
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
+ ERR_FAIL_COND(!shadow_atlas);
+ ERR_FAIL_INDEX(p_quadrant, 4);
+ ERR_FAIL_INDEX(p_subdivision, 16384);
+
+ uint32_t subdiv = next_power_of_2(p_subdivision);
+ if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer
+ subdiv <<= 1;
+ }
+
+ subdiv = int(Math::sqrt((float)subdiv));
+
+ //obtain the number that will be x*x
+
+ if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv)
+ return;
+
+ //erase all data from quadrant
+ for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) {
+
+ if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) {
+ shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
+ LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
+ ERR_CONTINUE(!li);
+ li->shadow_atlases.erase(p_atlas);
+ }
+ }
+
+ shadow_atlas->quadrants[p_quadrant].shadows.resize(0);
+ shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv);
+ shadow_atlas->quadrants[p_quadrant].subdivision = subdiv;
+
+ //cache the smallest subdiv (for faster allocation in light update)
+
+ shadow_atlas->smallest_subdiv = 1 << 30;
+
+ for (int i = 0; i < 4; i++) {
+ if (shadow_atlas->quadrants[i].subdivision) {
+ shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision);
+ }
+ }
+
+ if (shadow_atlas->smallest_subdiv == 1 << 30) {
+ shadow_atlas->smallest_subdiv = 0;
+ }
+
+ //resort the size orders, simple bublesort for 4 elements..
+
+ int swaps = 0;
+ do {
+ swaps = 0;
+
+ for (int i = 0; i < 3; i++) {
+ if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) {
+ SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]);
+ swaps++;
+ }
+ }
+ } while (swaps > 0);
+}
+
+bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) {
+
+ for (int i = p_quadrant_count - 1; i >= 0; i--) {
+
+ int qidx = p_in_quadrants[i];
+
+ if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {
+ return false;
+ }
+
+ //look for an empty space
+ int sc = shadow_atlas->quadrants[qidx].shadows.size();
+ ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptrw();
+
+ int found_free_idx = -1; //found a free one
+ int found_used_idx = -1; //found existing one, must steal it
+ uint64_t min_pass = 0; // pass of the existing one, try to use the least recently used one (LRU fashion)
+
+ for (int j = 0; j < sc; j++) {
+ if (!sarr[j].owner.is_valid()) {
+ found_free_idx = j;
+ break;
+ }
+
+ LightInstance *sli = light_instance_owner.getornull(sarr[j].owner);
+ ERR_CONTINUE(!sli);
+
+ if (sli->last_scene_pass != scene_pass) {
+
+ //was just allocated, don't kill it so soon, wait a bit..
+ if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec)
+ continue;
+
+ if (found_used_idx == -1 || sli->last_scene_pass < min_pass) {
+ found_used_idx = j;
+ min_pass = sli->last_scene_pass;
+ }
+ }
+ }
+
+ if (found_free_idx == -1 && found_used_idx == -1)
+ continue; //nothing found
+
+ if (found_free_idx == -1 && found_used_idx != -1) {
+ found_free_idx = found_used_idx;
+ }
+
+ r_quadrant = qidx;
+ r_shadow = found_free_idx;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool RasterizerSceneRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) {
+
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
+ ERR_FAIL_COND_V(!shadow_atlas, false);
+
+ LightInstance *li = light_instance_owner.getornull(p_light_intance);
+ ERR_FAIL_COND_V(!li, false);
+
+ if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) {
+ return false;
+ }
+
+ uint32_t quad_size = shadow_atlas->size >> 1;
+ int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage));
+
+ int valid_quadrants[4];
+ int valid_quadrant_count = 0;
+ int best_size = -1; //best size found
+ int best_subdiv = -1; //subdiv for the best size
+
+ //find the quadrants this fits into, and the best possible size it can fit into
+ for (int i = 0; i < 4; i++) {
+ int q = shadow_atlas->size_order[i];
+ int sd = shadow_atlas->quadrants[q].subdivision;
+ if (sd == 0)
+ continue; //unused
+
+ int max_fit = quad_size / sd;
+
+ if (best_size != -1 && max_fit > best_size)
+ break; //too large
+
+ valid_quadrants[valid_quadrant_count++] = q;
+ best_subdiv = sd;
+
+ if (max_fit >= desired_fit) {
+ best_size = max_fit;
+ }
+ }
+
+ ERR_FAIL_COND_V(valid_quadrant_count == 0, false);
+
+ uint64_t tick = OS::get_singleton()->get_ticks_msec();
+
+ //see if it already exists
+
+ if (shadow_atlas->shadow_owners.has(p_light_intance)) {
+ //it does!
+ uint32_t key = shadow_atlas->shadow_owners[p_light_intance];
+ uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
+ uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+ bool should_realloc = shadow_atlas->quadrants[q].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec);
+ bool should_redraw = shadow_atlas->quadrants[q].shadows[s].version != p_light_version;
+
+ if (!should_realloc) {
+ shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version;
+ //already existing, see if it should redraw or it's just OK
+ return should_redraw;
+ }
+
+ int new_quadrant, new_shadow;
+
+ //find a better place
+ if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, shadow_atlas->quadrants[q].subdivision, tick, new_quadrant, new_shadow)) {
+ //found a better place!
+ ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
+ if (sh->owner.is_valid()) {
+ //is taken, but is invalid, erasing it
+ shadow_atlas->shadow_owners.erase(sh->owner);
+ LightInstance *sli = light_instance_owner.getornull(sh->owner);
+ sli->shadow_atlases.erase(p_atlas);
+ }
+
+ //erase previous
+ shadow_atlas->quadrants[q].shadows.write[s].version = 0;
+ shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
+
+ sh->owner = p_light_intance;
+ sh->alloc_tick = tick;
+ sh->version = p_light_version;
+ li->shadow_atlases.insert(p_atlas);
+
+ //make new key
+ key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
+ key |= new_shadow;
+ //update it in map
+ shadow_atlas->shadow_owners[p_light_intance] = key;
+ //make it dirty, as it should redraw anyway
+ return true;
+ }
+
+ //no better place for this shadow found, keep current
+
+ //already existing, see if it should redraw or it's just OK
+
+ shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version;
+
+ return should_redraw;
+ }
+
+ int new_quadrant, new_shadow;
+
+ //find a better place
+ if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, -1, tick, new_quadrant, new_shadow)) {
+ //found a better place!
+ ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
+ if (sh->owner.is_valid()) {
+ //is taken, but is invalid, erasing it
+ shadow_atlas->shadow_owners.erase(sh->owner);
+ LightInstance *sli = light_instance_owner.getornull(sh->owner);
+ sli->shadow_atlases.erase(p_atlas);
+ }
+
+ sh->owner = p_light_intance;
+ sh->alloc_tick = tick;
+ sh->version = p_light_version;
+ li->shadow_atlases.insert(p_atlas);
+
+ //make new key
+ uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
+ key |= new_shadow;
+ //update it in map
+ shadow_atlas->shadow_owners[p_light_intance] = key;
+ //make it dirty, as it should redraw anyway
+
+ return true;
+ }
+
+ //no place to allocate this light, apologies
+
+ return false;
+}
+
+void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) {
+
+ p_size = nearest_power_of_2_templated(p_size);
+
+ if (directional_shadow.size == p_size) {
+ return;
+ }
+
+ if (directional_shadow.depth.is_valid()) {
+ RD::get_singleton()->free(directional_shadow.depth);
+ directional_shadow.depth = RID();
+ directional_shadow.fb = RID();
+ }
+
+ if (p_size > 0) {
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R32_SFLOAT;
+ tf.width = p_size;
+ tf.height = p_size;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ Vector<RID> fb;
+ fb.push_back(directional_shadow.depth);
+ directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+}
+
+void RasterizerSceneRD::set_directional_shadow_count(int p_count) {
+
+ directional_shadow.light_count = p_count;
+ directional_shadow.current_light = 0;
+}
+
+int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) {
+
+ ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
+
+ int shadow_size;
+
+ if (directional_shadow.light_count == 1) {
+ shadow_size = directional_shadow.size;
+ } else {
+ shadow_size = directional_shadow.size / 2; //more than 4 not supported anyway
+ }
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_light_intance);
+ ERR_FAIL_COND_V(!light_instance, 0);
+
+ switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
+ case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
+ break; //none
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break;
+ }
+
+ return shadow_size;
+}
+
+//////////////////////////////////////////////////
+
+RID RasterizerSceneRD::light_instance_create(RID p_light) {
+
+ RID li = light_instance_owner.make_rid(LightInstance());
+
+ LightInstance *light_instance = light_instance_owner.getornull(li);
+
+ light_instance->self = li;
+ light_instance->light = p_light;
+ light_instance->light_type = storage->light_get_type(p_light);
+
+ return li;
+}
+
+void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ light_instance->transform = p_transform;
+}
+
+void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) {
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ if (storage->light_get_type(light_instance->light) != VS::LIGHT_DIRECTIONAL) {
+ p_pass = 0;
+ }
+
+ ERR_FAIL_INDEX(p_pass, 4);
+
+ light_instance->shadow_transform[p_pass].camera = p_projection;
+ light_instance->shadow_transform[p_pass].transform = p_transform;
+ light_instance->shadow_transform[p_pass].farplane = p_far;
+ light_instance->shadow_transform[p_pass].split = p_split;
+ light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;
+}
+
+void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) {
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ light_instance->last_scene_pass = scene_pass;
+}
+
+RasterizerSceneRD::ShadowCubemap *RasterizerSceneRD::_get_shadow_cubemap(int p_size) {
+
+ if (!shadow_cubemaps.has(p_size)) {
+
+ ShadowCubemap sc;
+ {
+ 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 = p_size;
+ tf.height = p_size;
+ tf.type = RD::TEXTURE_TYPE_CUBE;
+ tf.array_layers = 6;
+ tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ sc.cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+
+ for (int i = 0; i < 6; i++) {
+ RID side_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sc.cubemap, i, 0);
+ Vector<RID> fbtex;
+ fbtex.push_back(side_texture);
+ sc.side_fb[i] = RD::get_singleton()->framebuffer_create(fbtex);
+ }
+
+ shadow_cubemaps[p_size] = sc;
+ }
+
+ return &shadow_cubemaps[p_size];
+}
+
+RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p_size) {
+
+ if (!shadow_maps.has(p_size)) {
+
+ ShadowMap sm;
+ {
+ 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 = p_size.width;
+ tf.height = p_size.height;
+ tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ sm.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+
+ Vector<RID> fbtex;
+ fbtex.push_back(sm.depth);
+ sm.fb = RD::get_singleton()->framebuffer_create(fbtex);
+
+ shadow_maps[p_size] = sm;
+ }
+
+ return &shadow_maps[p_size];
+}
+
+////////////////////////////////
RID RasterizerSceneRD::render_buffers_create() {
RenderBuffers rb;
rb.data = _create_render_buffer_data();
@@ -440,12 +1078,200 @@ 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_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_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_atlas, p_reflection_probe, p_reflection_probe_pass);
+ _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);
+}
+
+void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_light);
+ ERR_FAIL_COND(!light_instance);
+
+ Rect2i atlas_rect;
+ RID atlas_fb;
+ int atlas_fb_size;
+
+ bool using_dual_paraboloid = false;
+ bool using_dual_paraboloid_flip = false;
+ float zfar = 0;
+ RID render_fb;
+ RID render_texture;
+ float bias = 0;
+ float normal_bias = 0;
+
+ bool render_cubemap = false;
+ bool finalize_cubemap = false;
+
+ CameraMatrix light_projection;
+ Transform light_transform;
+
+ if (storage->light_get_type(light_instance->light) == VS::LIGHT_DIRECTIONAL) {
+ //set pssm stuff
+ if (light_instance->last_scene_shadow_pass != scene_pass) {
+ //assign rect if unassigned
+ light_instance->light_directional_index = directional_shadow.current_light;
+ light_instance->last_scene_shadow_pass = scene_pass;
+ directional_shadow.current_light++;
+
+ if (directional_shadow.light_count == 1) {
+ light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size);
+ } else if (directional_shadow.light_count == 2) {
+ light_instance->directional_rect = Rect2(0, 0, directional_shadow.size, directional_shadow.size / 2);
+ if (light_instance->light_directional_index == 1) {
+ light_instance->directional_rect.position.x += light_instance->directional_rect.size.x;
+ }
+ } else { //3 and 4
+ light_instance->directional_rect = Rect2(0, 0, directional_shadow.size / 2, directional_shadow.size / 2);
+ if (light_instance->light_directional_index & 1) {
+ light_instance->directional_rect.position.x += light_instance->directional_rect.size.x;
+ }
+ if (light_instance->light_directional_index / 2) {
+ light_instance->directional_rect.position.y += light_instance->directional_rect.size.y;
+ }
+ }
+ }
+
+ light_projection = light_instance->shadow_transform[p_pass].camera;
+ light_transform = light_instance->shadow_transform[p_pass].transform;
+
+ atlas_rect.position.x = light_instance->directional_rect.position.x;
+ atlas_rect.position.y = light_instance->directional_rect.position.y;
+ atlas_rect.size.width = light_instance->directional_rect.size.x;
+ atlas_rect.size.height = light_instance->directional_rect.size.y;
+
+ if (storage->light_directional_get_shadow_mode(light_instance->light) == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
+
+ atlas_rect.size.width /= 2;
+ atlas_rect.size.height /= 2;
+
+ if (p_pass == 1) {
+ atlas_rect.position.x += atlas_rect.size.width;
+ } else if (p_pass == 2) {
+ atlas_rect.position.y += atlas_rect.size.height;
+ } else if (p_pass == 3) {
+ atlas_rect.position.x += atlas_rect.size.width;
+ atlas_rect.position.y += atlas_rect.size.height;
+ }
+
+ } else if (storage->light_directional_get_shadow_mode(light_instance->light) == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
+
+ atlas_rect.size.height /= 2;
+
+ if (p_pass == 0) {
+
+ } else {
+ atlas_rect.position.y += atlas_rect.size.height;
+ }
+ }
+
+ float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE));
+ zfar = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_RANGE);
+ bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;
+ normal_bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * bias_mult;
+
+ ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
+ render_fb = shadow_map->fb;
+ render_texture = shadow_map->depth;
+ atlas_fb = directional_shadow.fb;
+ atlas_fb_size = directional_shadow.size;
+
+ } else {
+ //set from shadow atlas
+
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ ERR_FAIL_COND(!shadow_atlas);
+ ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light));
+
+ uint32_t key = shadow_atlas->shadow_owners[p_light];
+
+ uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
+ uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+ ERR_FAIL_INDEX((int)shadow, shadow_atlas->quadrants[quadrant].shadows.size());
+
+ uint32_t quadrant_size = shadow_atlas->size >> 1;
+
+ atlas_rect.position.x = (quadrant & 1) * quadrant_size;
+ atlas_rect.position.y = (quadrant >> 1) * quadrant_size;
+
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+ atlas_rect.position.x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ atlas_rect.position.y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+
+ atlas_rect.size.width = shadow_size;
+ atlas_rect.size.height = shadow_size;
+ atlas_fb = shadow_atlas->fb;
+ atlas_fb_size = shadow_atlas->size;
+
+ zfar = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_RANGE);
+ bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS);
+ normal_bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS);
+
+ if (storage->light_get_type(light_instance->light) == VS::LIGHT_OMNI) {
+
+ if (storage->light_omni_get_shadow_mode(light_instance->light) == VS::LIGHT_OMNI_SHADOW_CUBE) {
+
+ ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2);
+
+ render_fb = cubemap->side_fb[p_pass];
+ render_texture = cubemap->cubemap;
+
+ light_projection = light_instance->shadow_transform[0].camera;
+ light_transform = light_instance->shadow_transform[0].transform;
+ render_cubemap = true;
+ finalize_cubemap = p_pass == 5;
+
+ } else {
+
+ light_projection = light_instance->shadow_transform[0].camera;
+ light_transform = light_instance->shadow_transform[0].transform;
+
+ atlas_rect.size.height /= 2;
+ atlas_rect.position.y += p_pass * atlas_rect.size.height;
+
+ using_dual_paraboloid = true;
+ using_dual_paraboloid_flip = p_pass == 1;
+
+ ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
+ render_fb = shadow_map->fb;
+ render_texture = shadow_map->depth;
+ }
+
+ } else if (storage->light_get_type(light_instance->light) == VS::LIGHT_SPOT) {
+
+ light_projection = light_instance->shadow_transform[0].camera;
+ light_transform = light_instance->shadow_transform[0].transform;
+
+ ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
+ render_fb = shadow_map->fb;
+ render_texture = shadow_map->depth;
+ }
+ }
+
+ if (render_cubemap) {
+ //rendering to cubemap
+ _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false);
+ if (finalize_cubemap) {
+ //reblit
+ atlas_rect.size.height /= 2;
+ storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, false);
+ atlas_rect.position.y += atlas_rect.size.height;
+ storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, true);
+ }
+ } else {
+ //render shadow
+ _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip);
+
+ //copy to atlas
+ storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true);
+
+ //does not work from depth to color
+ //RD::get_singleton()->texture_copy(render_texture, atlas_texture, Vector3(0, 0, 0), Vector3(atlas_rect.position.x, atlas_rect.position.y, 0), Vector3(atlas_rect.size.x, atlas_rect.size.y, 1), 0, 0, 0, 0, true);
+ }
}
bool RasterizerSceneRD::free(RID p_rid) {
@@ -457,11 +1283,39 @@ 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_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_instance_owner.free(p_rid);
} else if (sky_owner.owns(p_rid)) {
_update_dirty_skys();
Sky *sky = sky_owner.getornull(p_rid);
- RD::get_singleton()->free(sky->radiance); //free radiance, everything else gets dependency-erased
+ _clear_reflection_data(sky->reflection);
sky_owner.free(p_rid);
+ } else if (light_instance_owner.owns(p_rid)) {
+
+ LightInstance *light_instance = light_instance_owner.getornull(p_rid);
+
+ //remove from shadow atlases..
+ for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(E->get());
+ ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid));
+ uint32_t key = shadow_atlas->shadow_owners[p_rid];
+ uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
+ uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+ shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
+ shadow_atlas->shadow_owners.erase(p_rid);
+ }
+
+ light_instance_owner.free(p_rid);
+
+ } else if (shadow_atlas_owner.owns(p_rid)) {
+
+ shadow_atlas_set_size(p_rid, 0);
+ shadow_atlas_owner.free(p_rid);
+
} else {
return false;
}
@@ -482,3 +1336,14 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) {
sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");
sky_use_cubemap_array = false;
}
+
+RasterizerSceneRD::~RasterizerSceneRD() {
+ directional_shadow_atlas_set_size(0);
+
+ for (Map<Vector2i, ShadowMap>::Element *E = shadow_maps.front(); E; E = E->next()) {
+ RD::get_singleton()->free(E->get().depth);
+ }
+ for (Map<int, ShadowCubemap>::Element *E = shadow_cubemaps.front(); E; E = E->next()) {
+ RD::get_singleton()->free(E->get().cubemap);
+ }
+}
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
index c333c4b10c..83316079d1 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
@@ -15,20 +15,17 @@ 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_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_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:
int roughness_layers;
RasterizerStorageRD *storage;
- struct Sky {
- int radiance_size = 256;
- VS::SkyMode mode = VS::SKY_MODE_QUALITY;
- RID panorama;
+ struct ReflectionData {
RID radiance;
- bool dirty = false;
- Sky *dirty_list = nullptr;
+
struct Layer {
struct Mipmap {
RID framebuffers[6];
@@ -38,9 +35,26 @@ private:
Vector<Mipmap> mipmaps;
};
RID radiance_base_cubemap; //cubemap for first layer, first cubemap
+
Vector<Layer> layers;
};
+ void _clear_reflection_data(ReflectionData &rd);
+ void _update_reflection_data(ReflectionData &rd, int p_size, bool p_quality);
+ 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 _update_reflection_mipmaps(ReflectionData &rd, bool p_quality);
+
+ /* SKY */
+ struct Sky {
+ int radiance_size = 256;
+ VS::SkyMode mode = VS::SKY_MODE_QUALITY;
+ RID panorama;
+ ReflectionData reflection;
+ bool dirty = false;
+ Sky *dirty_list = nullptr;
+ };
+
Sky *dirty_sky_list = nullptr;
void _sky_invalidate(Sky *p_sky);
@@ -52,6 +66,156 @@ private:
mutable RID_Owner<Sky> sky_owner;
+ /* REFLECTION PROBE INSTANCE */
+
+ struct ReflectionProbeInstance {
+
+ RID probe;
+
+ ReflectionData reflection;
+ RID depth_buffer;
+ RID render_fb[6];
+
+ int current_resolution = 0;
+
+ bool dirty = true;
+ bool rendering = false;
+ int processing_side = 0;
+
+ uint32_t render_index = 0;
+
+ Transform transform;
+ };
+
+ mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
+
+ /* SHADOW ATLAS */
+
+ struct ShadowAtlas {
+
+ enum {
+ QUADRANT_SHIFT = 27,
+ SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1,
+ SHADOW_INVALID = 0xFFFFFFFF
+ };
+
+ struct Quadrant {
+
+ uint32_t subdivision;
+
+ struct Shadow {
+ RID owner;
+ uint64_t version;
+ uint64_t alloc_tick;
+
+ Shadow() {
+ version = 0;
+ alloc_tick = 0;
+ }
+ };
+
+ Vector<Shadow> shadows;
+
+ Quadrant() {
+ subdivision = 0; //not in use
+ }
+
+ } quadrants[4];
+
+ int size_order[4] = { 0, 1, 2, 3 };
+ uint32_t smallest_subdiv = 0;
+
+ int size = 0;
+
+ RID depth;
+ RID fb; //for copying
+
+ Map<RID, uint32_t> shadow_owners;
+ };
+
+ RID_Owner<ShadowAtlas> shadow_atlas_owner;
+
+ bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
+
+ /* DIRECTIONAL SHADOW */
+
+ struct DirectionalShadow {
+ RID depth;
+ RID fb; //for copying
+
+ int light_count = 0;
+ int size = 0;
+ int current_light = 0;
+ } directional_shadow;
+
+ /* SHADOW CUBEMAPS */
+
+ struct ShadowCubemap {
+
+ RID cubemap;
+ RID side_fb[6];
+ };
+
+ Map<int, ShadowCubemap> shadow_cubemaps;
+ ShadowCubemap *_get_shadow_cubemap(int p_size);
+
+ struct ShadowMap {
+ RID depth;
+ RID fb;
+ };
+
+ Map<Vector2i, ShadowMap> shadow_maps;
+ ShadowMap *_get_shadow_map(const Size2i &p_size);
+
+ void _create_shadow_cubemaps();
+
+ /* LIGHT INSTANCE */
+
+ struct LightInstance {
+
+ struct ShadowTransform {
+
+ CameraMatrix camera;
+ Transform transform;
+ float farplane;
+ float split;
+ float bias_scale;
+ };
+
+ VS::LightType light_type;
+
+ ShadowTransform shadow_transform[4];
+
+ RID self;
+ RID light;
+ Transform transform;
+
+ Vector3 light_vector;
+ Vector3 spot_vector;
+ float linear_att;
+
+ uint64_t shadow_pass = 0;
+ uint64_t last_scene_pass = 0;
+ uint64_t last_scene_shadow_pass = 0;
+ uint64_t last_pass = 0;
+ uint32_t light_index = 0;
+ uint32_t light_directional_index = 0;
+
+ uint32_t current_shadow_atlas_key;
+
+ Vector2 dp;
+
+ Rect2 directional_rect;
+
+ Set<RID> shadow_atlases; //shadow atlases where this light is registered
+
+ LightInstance() {}
+ };
+
+ mutable RID_Owner<LightInstance> light_instance_owner;
+
+ /* ENVIRONMENT */
+
struct Environent {
// BG
@@ -82,6 +246,8 @@ private:
mutable RID_Owner<Environent> environment_owner;
+ /* RENDER BUFFERS */
+
struct RenderBuffers {
RenderBufferData *data = nullptr;
@@ -92,16 +258,45 @@ private:
mutable RID_Owner<RenderBuffers> render_buffers_owner;
+ uint64_t scene_pass = 0;
+ uint64_t shadow_atlas_realloc_tolerance_msec = 500;
+
public:
/* SHADOW ATLAS API */
- RID shadow_atlas_create() { return RID(); }
- void shadow_atlas_set_size(RID p_atlas, int p_size) {}
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {}
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { return false; }
-
- int get_directional_light_shadow_size(RID p_light_intance) { return 0; }
- void set_directional_shadow_count(int p_count) {}
+ RID shadow_atlas_create();
+ void shadow_atlas_set_size(RID p_atlas, int p_size);
+ void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
+ bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
+ _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
+ ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+ ERR_FAIL_COND_V(!atlas, false);
+ return atlas->shadow_owners.has(p_light_intance);
+ }
+
+ _FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) {
+ ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+ ERR_FAIL_COND_V(!atlas, RID());
+ return atlas->depth;
+ }
+
+ _FORCE_INLINE_ Size2i shadow_atlas_get_size(RID p_atlas) {
+ ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas);
+ ERR_FAIL_COND_V(!atlas, Size2i());
+ return Size2(atlas->size, atlas->size);
+ }
+
+ void directional_shadow_atlas_set_size(int p_size);
+ int get_directional_light_shadow_size(RID p_light_intance);
+ void set_directional_shadow_count(int p_count);
+
+ _FORCE_INLINE_ RID directional_shadow_get_texture() {
+ return directional_shadow.depth;
+ }
+
+ _FORCE_INLINE_ Size2i directional_shadow_get_size() {
+ return Size2i(directional_shadow.size, directional_shadow.size);
+ }
/* SKY API */
@@ -166,22 +361,121 @@ public:
void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {}
void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {}
- RID light_instance_create(RID p_light) { return RID(); }
- void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {}
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) {}
- void light_instance_mark_visible(RID p_light_instance) {}
+ RID light_instance_create(RID p_light);
+ void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
+ void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
+ void light_instance_mark_visible(RID p_light_instance);
+
+ _FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->light;
+ }
+
+ _FORCE_INLINE_ Transform light_instance_get_base_transform(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->transform;
+ }
- RID reflection_atlas_create() { return RID(); }
- void reflection_atlas_set_size(RID p_ref_atlas, int p_size) {}
- void reflection_atlas_set_subdivision(RID p_ref_atlas, int p_subdiv) {}
+ _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas) {
- RID reflection_probe_instance_create(RID p_probe) { return RID(); }
- void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) {}
- void reflection_probe_release_atlas_index(RID p_instance) {}
- bool reflection_probe_instance_needs_redraw(RID p_instance) { return false; }
- bool reflection_probe_instance_has_reflection(RID p_instance) { return false; }
- bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { return false; }
- bool reflection_probe_instance_postprocess_step(RID p_instance) { return true; }
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ uint32_t key = shadow_atlas->shadow_owners[li->self];
+
+ uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
+ uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
+
+ ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2());
+
+ uint32_t atlas_size = shadow_atlas->size;
+ uint32_t quadrant_size = atlas_size >> 1;
+
+ uint32_t x = (quadrant & 1) * quadrant_size;
+ uint32_t y = (quadrant >> 1) * quadrant_size;
+
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+ x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+
+ uint32_t width = shadow_size;
+ uint32_t height = shadow_size;
+
+ return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size));
+ }
+
+ _FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
+
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->shadow_transform[p_index].camera;
+ }
+
+ _FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ li->last_pass = p_pass;
+ }
+
+ _FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->last_pass;
+ }
+
+ _FORCE_INLINE_ void light_instance_set_index(RID p_light_instance, uint32_t p_index) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ li->light_index = p_index;
+ }
+
+ _FORCE_INLINE_ uint32_t light_instance_get_index(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->light_index;
+ }
+
+ _FORCE_INLINE_ VS::LightType light_instance_get_type(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.getornull(p_light_instance);
+ return li->light_type;
+ }
+
+ virtual RID reflection_probe_instance_create(RID p_probe);
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform);
+ 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_postprocess_step(RID p_instance);
+
+ uint32_t reflection_probe_instance_get_resolution(RID p_instance);
+ RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index);
+
+ _FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, RID());
+
+ return rpi->probe;
+ }
+
+ _FORCE_INLINE_ void reflection_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND(!rpi);
+ rpi->render_index = p_render_index;
+ }
+
+ _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_index(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, 0);
+
+ return rpi->render_index;
+ }
+
+ _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());
+
+ return rpi->transform;
+ }
+
+ _FORCE_INLINE_ RID reflection_probe_instance_get_texture(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance);
+ ERR_FAIL_COND_V(!rpi, RID());
+
+ return rpi->reflection.radiance;
+ }
RID gi_probe_instance_create() { return RID(); }
void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {}
@@ -191,7 +485,12 @@ 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_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_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);
+
+ virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; }
+ _FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; }
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
@@ -201,6 +500,7 @@ public:
virtual void update();
RasterizerSceneRD(RasterizerStorageRD *p_storage);
+ ~RasterizerSceneRD();
};
#endif // RASTERIZER_SCENE_RD_H
diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
index 5ed90490dc..b5dffc7762 100644
--- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -2087,6 +2087,462 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su
v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
}
+/* LIGHT */
+
+RID RasterizerStorageRD::light_create(VS::LightType p_type) {
+
+ Light light;
+ light.type = p_type;
+
+ light.param[VS::LIGHT_PARAM_ENERGY] = 1.0;
+ light.param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+ light.param[VS::LIGHT_PARAM_SPECULAR] = 0.5;
+ light.param[VS::LIGHT_PARAM_RANGE] = 1.0;
+ light.param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45;
+ light.param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45;
+ light.param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
+ light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
+ light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
+ light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
+ light.param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1;
+ light.param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1;
+
+ return light_owner.make_rid(light);
+}
+
+void RasterizerStorageRD::light_set_color(RID p_light, const Color &p_color) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->color = p_color;
+}
+void RasterizerStorageRD::light_set_param(RID p_light, VS::LightParam p_param, float p_value) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+ ERR_FAIL_INDEX(p_param, VS::LIGHT_PARAM_MAX);
+
+ switch (p_param) {
+ case VS::LIGHT_PARAM_RANGE:
+ case VS::LIGHT_PARAM_SPOT_ANGLE:
+ case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
+ case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
+ case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
+ case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
+ case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
+ case VS::LIGHT_PARAM_SHADOW_BIAS: {
+
+ light->version++;
+ light->instance_dependency.instance_notify_changed(true, false);
+ } break;
+ default: {
+ }
+ }
+
+ light->param[p_param] = p_value;
+}
+void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+ light->shadow = p_enabled;
+
+ light->version++;
+ light->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+ light->shadow_color = p_color;
+}
+
+void RasterizerStorageRD::light_set_projector(RID p_light, RID p_texture) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->projector = p_texture;
+}
+
+void RasterizerStorageRD::light_set_negative(RID p_light, bool p_enable) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->negative = p_enable;
+}
+void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->cull_mask = p_mask;
+
+ light->version++;
+ light->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->reverse_cull = p_enabled;
+
+ light->version++;
+ light->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::light_set_use_gi(RID p_light, bool p_enabled) {
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->use_gi = p_enabled;
+
+ light->version++;
+ light->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->omni_shadow_mode = p_mode;
+
+ light->version++;
+ light->instance_dependency.instance_notify_changed(true, false);
+}
+
+VS::LightOmniShadowMode RasterizerStorageRD::light_omni_get_shadow_mode(RID p_light) {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI_SHADOW_CUBE);
+
+ return light->omni_shadow_mode;
+}
+
+void RasterizerStorageRD::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_shadow_mode = p_mode;
+ light->version++;
+ light->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_blend_splits = p_enable;
+ light->version++;
+ light->instance_dependency.instance_notify_changed(true, false);
+}
+
+bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, false);
+
+ return light->directional_blend_splits;
+}
+
+VS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
+
+ return light->directional_shadow_mode;
+}
+
+void RasterizerStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {
+
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_range_mode = p_range_mode;
+}
+
+VS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
+
+ return light->directional_range_mode;
+}
+
+bool RasterizerStorageRD::light_get_use_gi(RID p_light) {
+ Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, false);
+
+ return light->use_gi;
+}
+
+uint64_t RasterizerStorageRD::light_get_version(RID p_light) const {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->version;
+}
+
+AABB RasterizerStorageRD::light_get_aabb(RID p_light) const {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, AABB());
+
+ switch (light->type) {
+
+ case VS::LIGHT_SPOT: {
+
+ float len = light->param[VS::LIGHT_PARAM_RANGE];
+ float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len;
+ return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
+ };
+ case VS::LIGHT_OMNI: {
+
+ float r = light->param[VS::LIGHT_PARAM_RANGE];
+ return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
+ };
+ case VS::LIGHT_DIRECTIONAL: {
+
+ return AABB();
+ };
+ }
+
+ ERR_FAIL_V(AABB());
+}
+
+/* REFLECTION PROBE */
+
+RID RasterizerStorageRD::reflection_probe_create() {
+
+ return reflection_probe_owner.make_rid(ReflectionProbe());
+}
+
+void RasterizerStorageRD::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->update_mode = p_mode;
+ reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->intensity = p_intensity;
+}
+
+void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior_ambient = p_ambient;
+}
+
+void RasterizerStorageRD::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior_ambient_energy = p_energy;
+}
+
+void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior_ambient_probe_contrib = p_contrib;
+}
+
+void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->max_distance = p_distance;
+
+ reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->extents = p_extents;
+ reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->origin_offset = p_offset;
+ reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior = p_enable;
+ reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->box_projection = p_enable;
+}
+
+void RasterizerStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->enable_shadows = p_enable;
+ reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->cull_mask = p_layers;
+ reflection_probe->instance_dependency.instance_notify_changed(true, false);
+}
+
+void RasterizerStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+ ERR_FAIL_COND(p_resolution < 32);
+
+ reflection_probe->resolution = p_resolution;
+}
+
+AABB RasterizerStorageRD::reflection_probe_get_aabb(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, AABB());
+
+ AABB aabb;
+ aabb.position = -reflection_probe->extents;
+ aabb.size = reflection_probe->extents * 2.0;
+
+ return aabb;
+}
+VS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_mode(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS);
+
+ return reflection_probe->update_mode;
+}
+
+uint32_t RasterizerStorageRD::reflection_probe_get_cull_mask(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->cull_mask;
+}
+
+Vector3 RasterizerStorageRD::reflection_probe_get_extents(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+ return reflection_probe->extents;
+}
+Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+ return reflection_probe->origin_offset;
+}
+
+bool RasterizerStorageRD::reflection_probe_renders_shadows(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->enable_shadows;
+}
+
+float RasterizerStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->max_distance;
+}
+
+int RasterizerStorageRD::reflection_probe_get_resolution(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->resolution;
+}
+
+float RasterizerStorageRD::reflection_probe_get_intensity(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->intensity;
+}
+bool RasterizerStorageRD::reflection_probe_is_interior(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->interior;
+}
+bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->box_projection;
+}
+
+Color RasterizerStorageRD::reflection_probe_get_interior_ambient(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Color());
+
+ return reflection_probe->interior_ambient;
+}
+float RasterizerStorageRD::reflection_probe_get_interior_ambient_energy(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->interior_ambient_energy;
+}
+float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const {
+
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->interior_ambient_probe_contrib;
+}
+
/* RENDER TARGET API */
void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
@@ -2432,6 +2888,12 @@ void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::In
if (mesh_owner.owns(p_base)) {
Mesh *mesh = mesh_owner.getornull(p_base);
p_instance->update_dependency(&mesh->instance_dependency);
+ } else if (reflection_probe_owner.owns(p_base)) {
+ ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
+ p_instance->update_dependency(&rp->instance_dependency);
+ } else if (light_owner.owns(p_base)) {
+ Light *l = light_owner.getornull(p_base);
+ p_instance->update_dependency(&l->instance_dependency);
}
}
@@ -2440,6 +2902,13 @@ VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const {
if (mesh_owner.owns(p_rid)) {
return VS::INSTANCE_MESH;
}
+ if (reflection_probe_owner.owns(p_rid)) {
+ return VS::INSTANCE_REFLECTION_PROBE;
+ }
+ if (light_owner.owns(p_rid)) {
+ return VS::INSTANCE_LIGHT;
+ }
+
return VS::INSTANCE_NONE;
}
void RasterizerStorageRD::update_dirty_resources() {
@@ -2461,6 +2930,13 @@ bool RasterizerStorageRD::free(RID p_rid) {
RD::get_singleton()->free(t->rd_texture);
}
+ if (t->is_proxy && t->proxy_to.is_valid()) {
+ Texture *proxy_to = texture_owner.getornull(t->proxy_to);
+ if (proxy_to) {
+ proxy_to->proxies.erase(p_rid);
+ }
+ }
+
for (int i = 0; i < t->proxies.size(); i++) {
Texture *p = texture_owner.getornull(t->proxies[i]);
ERR_CONTINUE(!p);
@@ -2495,6 +2971,18 @@ bool RasterizerStorageRD::free(RID p_rid) {
Mesh *mesh = mesh_owner.getornull(p_rid);
mesh->instance_dependency.instance_notify_deleted(p_rid);
mesh_owner.free(p_rid);
+ } else if (reflection_probe_owner.owns(p_rid)) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
+ reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
+ reflection_probe_owner.free(p_rid);
+
+ } else if (light_owner.owns(p_rid)) {
+
+ // delete the texture
+ Light *light = light_owner.getornull(p_rid);
+ light->instance_dependency.instance_notify_deleted(p_rid);
+ light_owner.free(p_rid);
+
} else if (render_target_owner.owns(p_rid)) {
RenderTarget *rt = render_target_owner.getornull(p_rid);
@@ -2606,7 +3094,7 @@ RasterizerStorageRD::RasterizerStorageRD() {
tformat.height = 4;
tformat.array_layers = 6;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.type = RD::TEXTURE_TYPE_CUBE;
+ tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
PoolVector<uint8_t> pv;
pv.resize(16 * 4);
@@ -2634,7 +3122,7 @@ RasterizerStorageRD::RasterizerStorageRD() {
tformat.height = 4;
tformat.array_layers = 6;
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+ tformat.type = RD::TEXTURE_TYPE_CUBE;
PoolVector<uint8_t> pv;
pv.resize(16 * 4);
@@ -2680,34 +3168,6 @@ RasterizerStorageRD::RasterizerStorageRD() {
}
}
- { //create default cubemap array
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.array_layers = 6;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY;
-
- PoolVector<uint8_t> pv;
- pv.resize(16 * 4);
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 0);
- pv.set(i * 4 + 1, 0);
- pv.set(i * 4 + 2, 0);
- pv.set(i * 4 + 3, 0);
- }
-
- {
- Vector<PoolVector<uint8_t> > vpv;
- for (int i = 0; i < 6; i++) {
- vpv.push_back(pv);
- }
- default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
- }
-
//default samplers
for (int i = 1; i < VS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
for (int j = 1; j < VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
index 4059331790..3cfd5601e8 100644
--- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
@@ -251,6 +251,12 @@ private:
RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed
RID material;
+
+ uint32_t render_index = 0;
+ uint64_t render_pass = 0;
+
+ uint32_t multimesh_render_index = 0;
+ uint64_t multimesh_render_pass = 0;
};
uint32_t blend_shape_count = 0;
@@ -275,6 +281,54 @@ private:
RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
+ /* LIGHT */
+
+ struct Light {
+
+ VS::LightType type;
+ float param[VS::LIGHT_PARAM_MAX];
+ Color color = Color(1, 1, 1, 1);
+ Color shadow_color;
+ RID projector;
+ bool shadow = false;
+ bool negative = false;
+ bool reverse_cull = false;
+ bool use_gi = true;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ VS::LightOmniShadowMode omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+ VS::LightDirectionalShadowMode directional_shadow_mode = VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+ VS::LightDirectionalShadowDepthRangeMode directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
+ bool directional_blend_splits = false;
+ uint64_t version = 0;
+
+ RasterizerScene::InstanceDependency instance_dependency;
+ };
+
+ mutable RID_Owner<Light> light_owner;
+
+ /* REFLECTION PROBE */
+
+ struct ReflectionProbe {
+
+ VS::ReflectionProbeUpdateMode update_mode = VS::REFLECTION_PROBE_UPDATE_ONCE;
+ int resolution = 256;
+ float intensity = 1.0;
+ Color interior_ambient;
+ float interior_ambient_energy = 1.0;
+ float interior_ambient_probe_contrib = 0.0;
+ float max_distance = 0;
+ Vector3 extents = Vector3(1, 1, 1);
+ Vector3 origin_offset;
+ bool interior = false;
+ bool box_projection = false;
+ bool enable_shadows = false;
+ uint32_t cull_mask = (1 << 20) - 1;
+
+ RasterizerScene::InstanceDependency instance_dependency;
+ };
+
+ mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
+
/* RENDER TARGET */
struct RenderTarget {
@@ -530,6 +584,32 @@ public:
return mesh_default_rd_buffers[p_buffer];
}
+ _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->render_pass != p_render_pass) {
+ (*r_index)++;
+ s->render_pass = p_render_pass;
+ s->render_index = *r_index;
+ }
+
+ return s->render_index;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->multimesh_render_pass != p_render_pass) {
+ (*r_index)++;
+ s->multimesh_render_pass = p_render_pass;
+ s->multimesh_render_index = *r_index;
+ }
+
+ return s->multimesh_render_index;
+ }
+
/* MULTIMESH API */
virtual RID multimesh_create() { return RID(); }
@@ -587,68 +667,125 @@ public:
/* Light API */
- RID light_create(VS::LightType p_type) { return RID(); }
+ RID light_create(VS::LightType p_type);
RID directional_light_create() { return light_create(VS::LIGHT_DIRECTIONAL); }
RID omni_light_create() { return light_create(VS::LIGHT_OMNI); }
RID spot_light_create() { return light_create(VS::LIGHT_SPOT); }
- void light_set_color(RID p_light, const Color &p_color) {}
- void light_set_param(RID p_light, VS::LightParam p_param, float p_value) {}
- void light_set_shadow(RID p_light, bool p_enabled) {}
- void light_set_shadow_color(RID p_light, const Color &p_color) {}
- void light_set_projector(RID p_light, RID p_texture) {}
- void light_set_negative(RID p_light, bool p_enable) {}
- void light_set_cull_mask(RID p_light, uint32_t p_mask) {}
- void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {}
- void light_set_use_gi(RID p_light, bool p_enabled) {}
-
- void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {}
- void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) {}
-
- void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) {}
- void light_directional_set_blend_splits(RID p_light, bool p_enable) {}
- bool light_directional_get_blend_splits(RID p_light) const { return false; }
- void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {}
- VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const { return VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; }
-
- VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) { return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
- VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) { return VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
-
- bool light_has_shadow(RID p_light) const { return false; }
-
- VS::LightType light_get_type(RID p_light) const { return VS::LIGHT_OMNI; }
- AABB light_get_aabb(RID p_light) const { return AABB(); }
- float light_get_param(RID p_light, VS::LightParam p_param) { return 0.0; }
- Color light_get_color(RID p_light) { return Color(); }
- bool light_get_use_gi(RID p_light) { return false; }
- uint64_t light_get_version(RID p_light) const { return 0; }
+ void light_set_color(RID p_light, const Color &p_color);
+ void light_set_param(RID p_light, VS::LightParam p_param, float p_value);
+ void light_set_shadow(RID p_light, bool p_enabled);
+ void light_set_shadow_color(RID p_light, const Color &p_color);
+ void light_set_projector(RID p_light, RID p_texture);
+ void light_set_negative(RID p_light, bool p_enable);
+ void light_set_cull_mask(RID p_light, uint32_t p_mask);
+ void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
+ void light_set_use_gi(RID p_light, bool p_enabled);
+
+ void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode);
+
+ void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode);
+ void light_directional_set_blend_splits(RID p_light, bool p_enable);
+ bool light_directional_get_blend_splits(RID p_light) const;
+ void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode);
+ VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
+
+ VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
+ VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
+
+ _FORCE_INLINE_ VS::LightType light_get_type(RID p_light) const {
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
+
+ return light->type;
+ }
+ AABB light_get_aabb(RID p_light) const;
+
+ _FORCE_INLINE_ float light_get_param(RID p_light, VS::LightParam p_param) {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->param[p_param];
+ }
+
+ _FORCE_INLINE_ Color light_get_color(RID p_light) {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, Color());
+
+ return light->color;
+ }
+
+ _FORCE_INLINE_ Color light_get_shadow_color(RID p_light) {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, Color());
+
+ return light->shadow_color;
+ }
+
+ _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->cull_mask;
+ }
+
+ _FORCE_INLINE_ bool light_has_shadow(RID p_light) const {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
+
+ return light->shadow;
+ }
+
+ _FORCE_INLINE_ bool light_is_negative(RID p_light) const {
+
+ const Light *light = light_owner.getornull(p_light);
+ ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL);
+
+ return light->negative;
+ }
+
+ bool light_get_use_gi(RID p_light);
+ uint64_t light_get_version(RID p_light) const;
/* PROBE API */
- RID reflection_probe_create() { return RID(); }
-
- void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {}
- void reflection_probe_set_intensity(RID p_probe, float p_intensity) {}
- void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {}
- void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {}
- void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {}
- void reflection_probe_set_max_distance(RID p_probe, float p_distance) {}
- void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {}
- void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {}
- void reflection_probe_set_as_interior(RID p_probe, bool p_enable) {}
- void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {}
- void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {}
- void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {}
- void reflection_probe_set_resolution(RID p_probe, int p_resolution) {}
-
- AABB reflection_probe_get_aabb(RID p_probe) const { return AABB(); }
- VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const { return VisualServer::REFLECTION_PROBE_UPDATE_ONCE; }
- uint32_t reflection_probe_get_cull_mask(RID p_probe) const { return 0; }
- Vector3 reflection_probe_get_extents(RID p_probe) const { return Vector3(); }
- Vector3 reflection_probe_get_origin_offset(RID p_probe) const { return Vector3(); }
- float reflection_probe_get_origin_max_distance(RID p_probe) const { return 0.0; }
- bool reflection_probe_renders_shadows(RID p_probe) const { return false; }
+ RID reflection_probe_create();
+
+ void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode);
+ void reflection_probe_set_intensity(RID p_probe, float p_intensity);
+ void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient);
+ void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy);
+ void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib);
+ void reflection_probe_set_max_distance(RID p_probe, float p_distance);
+ void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents);
+ void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset);
+ void reflection_probe_set_as_interior(RID p_probe, bool p_enable);
+ void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
+ void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
+ void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
+ void reflection_probe_set_resolution(RID p_probe, int p_resolution);
+
+ AABB reflection_probe_get_aabb(RID p_probe) const;
+ VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
+ uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
+ Vector3 reflection_probe_get_extents(RID p_probe) const;
+ Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
+ float reflection_probe_get_origin_max_distance(RID p_probe) const;
+ int reflection_probe_get_resolution(RID p_probe) const;
+ bool reflection_probe_renders_shadows(RID p_probe) const;
+
+ float reflection_probe_get_intensity(RID p_probe) const;
+ bool reflection_probe_is_interior(RID p_probe) const;
+ bool reflection_probe_is_box_projection(RID p_probe) const;
+ Color reflection_probe_get_interior_ambient(RID p_probe) const;
+ float reflection_probe_get_interior_ambient_energy(RID p_probe) const;
+ float reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const;
void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance);
void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) {}
diff --git a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
index 2c3de2dbed..70404f2cfd 100644
--- a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
+++ b/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h
@@ -31,10 +31,13 @@
#ifndef RENDER_PIPELINE_CACHE_RD_H
#define RENDER_PIPELINE_CACHE_RD_H
+#include "core/spin_lock.h"
#include "servers/visual/rendering_device.h"
class RenderPipelineVertexFormatCacheRD {
+ SpinLock spin_lock;
+
RID shader;
uint32_t input_mask;
@@ -68,12 +71,19 @@ public:
ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
"Attempted to use an unused shader variant (shader is null),");
#endif
+
+ spin_lock.lock();
+ RID result;
for (uint32_t i = 0; i < version_count; i++) {
if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) {
- return versions[i].pipeline;
+ result = versions[i].pipeline;
+ spin_lock.unlock();
+ return result;
}
}
- return _generate_version(p_vertex_format_id, p_framebuffer_format_id);
+ result = _generate_version(p_vertex_format_id, p_framebuffer_format_id);
+ spin_lock.unlock();
+ return result;
}
_FORCE_INLINE_ uint32_t get_vertex_input_mask() const {
diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub
index 0a4bebcfbc..b1fa9cd3f4 100644
--- a/servers/visual/rasterizer_rd/shaders/SCsub
+++ b/servers/visual/rasterizer_rd/shaders/SCsub
@@ -10,4 +10,5 @@ if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('scene_forward.glsl');
env.RD_GLSL('sky.glsl');
env.RD_GLSL('tonemap.glsl');
+ env.RD_GLSL('copy.glsl');
diff --git a/servers/visual/rasterizer_rd/shaders/blur.glsl b/servers/visual/rasterizer_rd/shaders/blur.glsl
index 4f47595d2c..5907e911a3 100644
--- a/servers/visual/rasterizer_rd/shaders/blur.glsl
+++ b/servers/visual/rasterizer_rd/shaders/blur.glsl
@@ -23,6 +23,10 @@ void main() {
gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
+ if (bool(blur.flags&FLAG_FLIP_Y)) {
+ uv_interp.y = 1.0 - uv_interp.y;
+ }
+
}
/* clang-format off */
diff --git a/servers/visual/rasterizer_rd/shaders/blur_inc.glsl b/servers/visual/rasterizer_rd/shaders/blur_inc.glsl
index ea932130aa..275b547fc4 100644
--- a/servers/visual/rasterizer_rd/shaders/blur_inc.glsl
+++ b/servers/visual/rasterizer_rd/shaders/blur_inc.glsl
@@ -3,6 +3,7 @@
#define FLAG_USE_ORTHOGONAL_PROJECTION (1<<2)
#define FLAG_DOF_NEAR_FIRST_TAP (1<<3)
#define FLAG_GLOW_FIRST_PASS (1<<4)
+#define FLAG_FLIP_Y (1<<5)
layout(push_constant, binding = 1, std430) uniform Blur {
vec4 section;
diff --git a/servers/visual/rasterizer_rd/shaders/copy.glsl b/servers/visual/rasterizer_rd/shaders/copy.glsl
new file mode 100644
index 0000000000..e54b3972c0
--- /dev/null
+++ b/servers/visual/rasterizer_rd/shaders/copy.glsl
@@ -0,0 +1,93 @@
+/* clang-format off */
+[vertex]
+/* clang-format on */
+
+#version 450
+
+/* clang-format off */
+VERSION_DEFINES
+/* clang-format on */
+
+layout(location =0) out vec2 uv_interp;
+
+void main() {
+
+ vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
+
+}
+
+/* clang-format off */
+[fragment]
+/* clang-format on */
+
+#version 450
+
+/* clang-format off */
+VERSION_DEFINES
+/* clang-format on */
+
+layout(location =0) in vec2 uv_interp;
+
+#ifdef MODE_CUBE_TO_DP
+
+layout( set=0, binding=0 ) uniform samplerCube source_cube;
+
+layout(push_constant, binding = 0, std430) uniform Params {
+ float bias;
+ float z_far;
+ float z_near;
+ bool z_flip;
+
+} params;
+
+layout(location=0) out float depth_buffer;
+
+#endif
+
+
+void main() {
+
+#ifdef MODE_CUBE_TO_DP
+
+ vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
+
+ normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
+ normal = normalize(normal);
+
+
+ normal.y = -normal.y; //needs to be flipped to match projection matrix
+ if (!params.z_flip) {
+ normal.z = -normal.z;
+ }
+
+ float depth = texture(source_cube, normal).r;
+
+ // absolute values for direction cosines, bigger value equals closer to basis axis
+ vec3 unorm = abs(normal);
+
+ if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
+ // x code
+ unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
+ } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
+ // y code
+ unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
+ } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
+ // z code
+ unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
+ } else {
+ // oh-no we messed up code
+ // has to be
+ unorm = vec3(1.0, 0.0, 0.0);
+ }
+
+ float depth_fix = 1.0 / dot(normal, unorm);
+
+ depth = 2.0 * depth - 1.0;
+ float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+ depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
+
+#endif
+}
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
index df31d8c26f..3479929774 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
@@ -75,12 +75,26 @@ VERTEX_SHADER_GLOBALS
// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316
//invariant gl_Position;
+layout(location =7) flat out uint instance_index;
+
+#ifdef MODE_DUAL_PARABOLOID
+
+layout(location =8) out float dp_clip;
+
+#endif
+
void main() {
+ instance_index = draw_call.instance_index;
+
+ /*if (draw_call.instance_increment) {
+ instance_index += gl_InstanceIndex;
+ }*/
+
vec3 vertex = vertex_attrib;
- mat4 world_matrix = instance_data.transform;
- mat3 world_normal_matrix= instance_data.normal_transform;
+ mat4 world_matrix = instances.data[instance_index].transform;
+ mat3 world_normal_matrix= mat3(instances.data[instance_index].normal_transform);
vec3 normal = normal_attrib;
@@ -131,8 +145,8 @@ void main() {
float roughness = 1.0;
- mat4 modelview = scene_data.inv_camera_matrix * instance_data.transform;
- mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * instance_data.normal_transform;
+ mat4 modelview = scene_data.inv_camera_matrix * world_matrix;
+ mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix;
{
/* clang-format off */
@@ -179,14 +193,35 @@ VERTEX_SHADER_CODE
#ifdef MODE_RENDER_DEPTH
+#ifdef MODE_DUAL_PARABOLOID
+
+ vertex_interp.z *= scene_data.dual_paraboloid_side;
+ normal_interp.z *= scene_data.dual_paraboloid_side;
+
+ dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
+
+ //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
+
+ vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset;
+ float distance = length(vtx);
+ vtx = normalize(vtx);
+ vtx.xy /= 1.0 - vtx.z;
+ vtx.z = (distance / scene_data.z_far);
+ vtx.z = vtx.z * 2.0 - 1.0;
+
+ vertex_interp = vtx;
+#else
+
float z_ofs = scene_data.z_offset;
z_ofs += (1.0 - abs(normal_interp.z)) * scene_data.z_slope_scale;
vertex_interp.z -= z_ofs;
+#endif
+
#endif //MODE_RENDER_DEPTH
#ifdef USE_OVERRIDE_POSITION
- gl_Position = position;
+ gl_Position = position;;
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
@@ -227,10 +262,19 @@ layout(location = 5) in vec3 tangent_interp;
layout(location = 6) in vec3 binormal_interp;
#endif
+layout(location =7) flat in uint instance_index;
+
+#ifdef MODE_DUAL_PARABOLOID
+
+layout(location =8) in float dp_clip;
+
+#endif
+
+
//defines to keep compatibility with vertex
-#define world_matrix instance_data.transform;
-#define world_normal_matrix instance_data.normal_transform;
+#define world_matrix instances.data[instance_index].transform;
+#define world_normal_matrix instances.data[instance_index].normal_transform;
#define projection_matrix scene_data.projection_matrix;
#ifdef USE_MATERIAL_UNIFORMS
@@ -253,10 +297,14 @@ layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
#else
+#ifndef MODE_RENDER_DEPTH
layout(location = 0) out vec4 frag_color;
+#endif
#endif
+
+
// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V.
// We're dividing this factor off because the overall term we'll end up looks like
// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012):
@@ -329,7 +377,24 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, vec3 B, vec3 T, vec3 light_color, vec3 attenuation, vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float metallic, float specular, float rim, float rim_tint, float clearcoat, float clearcoat_gloss, float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light, inout float alpha) {
+void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color,float roughness, float metallic, float specular,float specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ vec3 transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ vec3 B, vec3 T,float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ inout float alpha,
+#endif
+ inout vec3 diffuse_light, inout vec3 specular_light
+ ) {
#if defined(USE_LIGHT_SHADER_CODE)
// light is written by the light shader
@@ -419,11 +484,11 @@ LIGHT_SHADER_CODE
diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation;
-#if defined(TRANSMISSION_USED)
+#if defined(LIGHT_TRANSMISSION_USED)
diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation;
#endif
-#if defined(RIM_LIGHT_USED)
+#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
#endif
@@ -517,9 +582,209 @@ LIGHT_SHADER_CODE
#endif //defined(USE_LIGHT_SHADER_CODE)
}
+#ifndef USE_NO_SHADOWS
+
+float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec2 pos, float depth) {
+
+#ifdef SHADOW_MODE_PCF_13
+
+ float avg = textureProj(shadow, vec4(pos, depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0));
+ return avg * (1.0 / 13.0);
+#endif
+
+#ifdef SHADOW_MODE_PCF_5
+
+ float avg = textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos, depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0));
+ avg += textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0));
+ return avg * (1.0 / 5.0);
+
+#endif
+
+#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13)
+
+ return textureProj(sampler2DShadow(shadow,shadow_sampler), vec4(pos, depth, 1.0));
+
+#endif
+}
+
+#endif //USE_NO_SHADOWS
+
+
+void light_process_omni(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,
+#endif
+#ifdef LIGHT_RIM_USED
+ float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ vec3 binormal, vec3 tangent, float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ inout float alpha,
+#endif
+ inout vec3 diffuse_light, inout vec3 specular_light) {
+
+ vec3 light_rel_vec = lights.data[idx].position - vertex;
+ float light_length = length(light_rel_vec);
+ float normalized_distance = light_length * lights.data[idx].inv_radius;
+ vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
+ float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
+ vec3 light_attenuation = vec3(omni_attenuation);
+ vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
+ color_specular.rgb*=attenuation_energy.y;
+
+#ifndef USE_NO_SHADOWS
+ vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
+ if (shadow_color_enabled.w > 0.5) {
+ // there is a shadowmap
+
+ vec3 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
+ float shadow_len = length(splane);
+ splane = normalize(splane);
+ vec4 clamp_rect = lights.data[idx].atlas_rect;
+
+ if (splane.z >= 0.0) {
+
+ splane.z += 1.0;
+
+ clamp_rect.y += clamp_rect.w;
+
+ } else {
+
+ splane.z = 1.0 - splane.z;
+
+ }
+
+ splane.xy /= splane.z;
+ splane.xy = splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len * lights.data[idx].inv_radius;
+
+ splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+ float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
+
+ light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ }
+#endif //USE_NO_SHADOWS
+
+ light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular,color_specular.a * p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ rim * omni_attenuation, rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ binormal, tangent, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha
+#endif
+ diffuse_light, specular_light);
+}
+
+
+
+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,
+#endif
+#ifdef LIGHT_RIM_USED
+ float rim, float rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ vec3 binormal, vec3 tangent, float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ inout float alpha
+#endif
+ inout vec3 diffuse_light, inout vec3 specular_light) {
+
+ vec3 light_rel_vec = lights.data[idx].position - vertex;
+ float light_length = length(light_rel_vec);
+ float normalized_distance = light_length * lights.data[idx].inv_radius;
+ vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
+ float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x);
+ vec3 spot_dir = lights.data[idx].direction;
+ vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle);
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
+ spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
+ vec3 light_attenuation = vec3(spot_attenuation);
+ vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
+ color_specular.rgb*=attenuation_energy.y;
+
+
+
+/*
+ if (lights.data[idx].atlas_rect!=vec4(0.0)) {
+ //use projector texture
+ }
+ */
+#ifndef USE_NO_SHADOWS
+ vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
+ if (shadow_color_enabled.w > 0.5) {
+ //there is a shadowmap
+ vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
+ splane.xyz /= splane.w;
+
+ float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane.xy, splane.z);
+
+ light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ }
+
+#endif //USE_NO_SHADOWS
+
+ light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular,color_specular.a * p_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ rim * omni_attenuation, rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ binormal, tangent, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha,
+#endif
+ diffuse_light, specular_light);
+}
void main() {
+#ifdef MODE_DUAL_PARABOLOID
+
+ if (dp_clip > 0.0)
+ discard;
+#endif
//lay out everything, whathever is unused is optimized away anyway
vec3 vertex = vertex_interp;
@@ -701,14 +966,149 @@ FRAGMENT_SHADER_CODE
specular_blob_intensity *= specular * 2.0;
#endif
+#ifndef MODE_RENDER_DEPTH
//gi probes
//lightmap
//lightmap capture
- //process reflections
+#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 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;
+
+ 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);
+
+#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;
+ }
+
+#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
+
+ }
+
+ if (reflection_accum.a > 0.0) {
+ specular_light = reflection_accum.rgb / reflection_accum.a;
+ }
+
+#if !defined(USE_LIGHTMAP)
+ if (ambient_accum.a > 0.0) {
+ ambient_light = ambient_accum.rgb / ambient_accum.a;
+ }
+#endif
+
+
+ }
+#endif //0
{
#if defined(DIFFUSE_TOON)
@@ -734,8 +1134,86 @@ FRAGMENT_SHADER_CODE
//directional light
+ { //omni lights
+ uint omni_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
+ for (uint i = 0; i < omni_light_count; i++) {
+
+ uint light_index = instances.data[instance_index].omni_light_indices[i>>1];
+
+ if (bool(i&1)) {
+ light_index>>=16;
+ } else {
+ light_index&=0xFFFF;
+ }
+
+ //this is done on CPU, so no need to do it here
+ //if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
+ // continue; //not masked
+ //}
+
+ light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular,specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ rim,
+ rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ tangent, binormal, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha,
+#endif
+ diffuse_light, specular_light);
+ }
+
+ }
+
+ { //spot lights
+ uint spot_light_count = (instances.data[instance_index].flags >> INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT) & INSTANCE_FLAGS_FORWARD_MASK;
+ for (uint i = 0; i < spot_light_count; i++) {
- //process omni and spots
+ uint light_index = instances.data[instance_index].spot_light_indices[i>>1];
+
+ if (bool(i&1)) {
+ light_index>>=16;
+ } else {
+ light_index&=0xFFFF;
+ }
+
+ //this is done on CPU, so no need to do it here
+ //if (!bool(lights.data[light_index].mask&instances.data[instance_index].layer_mask)) {
+ // continue; //not masked
+ //}
+
+ light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular,specular_blob_intensity,
+#ifdef LIGHT_TRANSMISSION_USED
+ transmission,
+#endif
+#ifdef LIGHT_RIM_USED
+ rim,
+ rim_tint,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ clearcoat, clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ tangent, binormal, anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ alpha,
+#endif
+ diffuse_light, specular_light);
+ }
+
+ }
+
+
+#endif //!MODE_RENDER_DEPTH
#ifdef USE_SHADOW_TO_OPACITY
alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
@@ -757,6 +1235,7 @@ FRAGMENT_SHADER_CODE
#endif // USE_SHADOW_TO_OPACITY
+
#ifdef MODE_RENDER_DEPTH
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
index 3547cad46c..8951f89c13 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
@@ -2,6 +2,13 @@
#define M_PI 3.14159265359
#define ROUGHNESS_MAX_LOD 5
+layout(push_constant, binding = 0, std430) uniform DrawCall {
+ uint instance_index;
+ uint pad[3]; //16 bits minimum size
+} draw_call;
+
+
+
/* Set 0 Scene data, screen and sources (changes the least) */
layout(set=0,binding=1) uniform texture2D depth_buffer;
@@ -35,7 +42,9 @@ layout(set = 0, binding = 5) uniform textureCube radiance_cubemap;
layout(set = 0, binding = 6) uniform sampler material_samplers[12];
-layout(set=0,binding=7,std140) uniform SceneData {
+layout(set = 0, binding = 7) uniform sampler shadow_sampler;
+
+layout(set=0,binding=8,std140) uniform SceneData {
mat4 projection_matrix;
mat4 inv_projection_matrix;
@@ -63,6 +72,14 @@ layout(set=0,binding=7,std140) uniform SceneData {
mat3 radiance_inverse_xform;
+ vec2 shadow_atlas_pixel_size;
+ vec2 directional_shadow_pixel_size;
+
+ uint directional_light_count;
+ float dual_paraboloid_side;
+ float z_far;
+ uint pad0;
+
#if 0
vec4 ambient_light_color;
vec4 bg_color;
@@ -101,80 +118,125 @@ layout(set=0,binding=7,std140) uniform SceneData {
#endif
} scene_data;
+#define INSTANCE_FLAGS_FORWARD_MASK 3
+#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3
+#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6
+#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9
+
+
+struct InstanceData {
+ mat4 transform;
+ mat4 normal_transform;
+ uint flags;
+ uint instance_ofs; //instance_offset in instancing/skeleton buffer
+ uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
+ uint layer_mask;
+
+ uint reflection_probe_indices[4];
+ uint omni_light_indices[4];
+ uint spot_light_indices[4];
+ uint decal_indices[4];
+};
+
+
+layout(set=0,binding=9,std430) buffer Instances {
+ InstanceData data[];
+} instances;
+
+struct ReflectionData {
+
+ vec4 box_extents;
+ vec4 box_offset;
+ 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
+ // notes: for ambientblend, use distance to edge to blend between already existing global environment
+};
+
+layout(set=0,binding=10,std140) uniform ReflectionProbeData {
+ ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
+} reflections;
+
+
+struct LightData { //this structure needs to be 128 bits
+
+ vec3 position;
+ float inv_radius;
+ vec3 direction;
+ uint attenuation_energy; //attenuation
+ uint color_specular; //rgb color, a specular (8 bit unorm)
+ uint cone_attenuation_angle; // attenuation and angle, (16bit float)
+ uint mask;
+ uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
+ vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
+ mat4 shadow_matrix;
+};
+
+layout(set=0,binding=11,std140) uniform Lights {
+ LightData data[MAX_LIGHT_DATA_STRUCTS];
+} lights;
+
+layout(set=0,binding=12) uniform texture2D shadow_atlas;
-#if 0
struct DirectionalLightData {
- vec4 light_pos_inv_radius;
- vec4 light_direction_attenuation;
- vec4 light_color_energy;
- vec4 light_params; // cone attenuation, angle, specular, shadow enabled,
- vec4 light_clamp;
- vec4 shadow_color_contact;
+ vec3 direction;
+ float energy;
+ vec3 color;
+ float specular;
+ uint mask;
+ uint pad0,pad1,pad2;
+ vec3 shadow_color;
+ bool shadow_enabled;
+ vec4 shadow_atlas_rect;
+ vec4 shadow_split_offsets;
mat4 shadow_matrix1;
mat4 shadow_matrix2;
mat4 shadow_matrix3;
mat4 shadow_matrix4;
- vec4 shadow_split_offsets;
+
};
-#endif
-/* Set 1 Skeleton Data (most objects lack it, so it changes little */
+layout(set=0,binding=13,std140) uniform DirectionalLights {
+ DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
+} directional_lights;
-#if 0
-layout(set = 1 binding = 0, std140) uniform SkeletonData {
- mat4 transform;
- bool use_skeleton;
- bool use_world_coords;
- bool pad1;
- bool pad2;
-} skeleton;
+layout(set=0,binding=14) uniform texture2D directional_shadow_atlas;
-layout(set = 1, binding = 1) uniform textureBuffer skeleton_bones;
-#endif
+/*
+layout(set=0,binding=15,std430) buffer Skeletons {
+ vec4 data[];
+} skeletons;
+*/
-/* Set 2 Custom Material Data (changess less than instance) */
+/* Set 1 Instancing (Multimesh) */
+//layout(set = 1, binding = 0) uniform textureBuffer multimesh_transforms;
-/* Set 3 Instance Data (Set on every draw call) */
+/* Set 2 Instancing (Multimesh) data */
-layout(push_constant, binding = 0, std430) uniform DrawData {
- //used in forward rendering, 16 bits indices, max 8
- uint reflection_probe_count;
- uint omni_light_count;
- uint spot_light_count;
- uint decal_count;
- uvec4 reflection_probe_indices;
- uvec4 omni_light_indices;
- uvec4 spot_light_indices;
- uvec4 decal_indices;
-} draw_data;
+#if 0
-layout(set = 3, binding = 0, std140) uniform InstanceData {
- mat4 transform;
- mat3 normal_transform;
- uint flags;
- uint pad0;
- uint pad1;
- uint pad2;
-} instance_data;
+#ifdef USE_RADIANCE_CUBEMAP_ARRAY
-layout(set = 3, binding = 1) uniform textureBuffer multimesh_transforms;
+layout(set = 3, binding = 2) uniform textureCubeArray reflection_probes[MAX_REFLECTION_PROBES];
-#ifdef USE_LIGHTMAP
+#else
-layout(set = 3, binding = 2) uniform texture2D lightmap;
+layout(set = 3, binding = 2) uniform textureCube reflection_probes[MAX_REFLECTION_PROBES];
#endif
+
#ifdef USE_VOXEL_CONE_TRACING
-layout(set = 3, binding = 3) uniform texture3D gi_probe[2];
+layout(set = 3, binding = 4) uniform texture3D gi_probe[2];
#ifdef USE_ANISOTROPIC_VOXEL_CONE_TRACING
-layout(set = 3, binding = 4) uniform texture3D gi_probe_aniso_pos[2];
-layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_neg[2];
+layout(set = 3, binding = 5) uniform texture3D gi_probe_aniso_pos[2];
+layout(set = 3, binding = 6) uniform texture3D gi_probe_aniso_neg[2];
#endif
#endif
+#endif
diff --git a/servers/visual/rasterizer_rd/shaders/tonemap.glsl b/servers/visual/rasterizer_rd/shaders/tonemap.glsl
index 284c934cf6..6797ff9f77 100644
--- a/servers/visual/rasterizer_rd/shaders/tonemap.glsl
+++ b/servers/visual/rasterizer_rd/shaders/tonemap.glsl
@@ -166,7 +166,9 @@ vec3 tonemap_reinhard(vec3 color, float white) {
return (white * color + color) / (color * white + white);
}
-vec3 linear_to_srgb(vec3 color) { // convert linear rgb to srgb, assumes clamped input in range [0;1]
+vec3 linear_to_srgb(vec3 color) {
+ //if going to srgb, clamp from 0 to 1.
+ color = clamp(color,vec3(0.0),vec3(1.0));
const vec3 a = vec3(0.055f);
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
}
@@ -233,15 +235,9 @@ vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blendi
return color + glow;
} else if (params.glow_mode==GLOW_MODE_SCREEN) {
//need color clamping
- color = clamp(color,0.0,1.0);
- glow = clamp(glow,0.0,1.0);
-
return max((color + glow) - (color * glow), vec3(0.0));
} else if ( params.glow_mode==GLOW_MODE_SOFTLIGHT) {
//need color clamping
- color = clamp(color,0.0,1.0);
- glow = clamp(glow,0.0,1.0);
-
glow = glow * vec3(0.5f) + vec3(0.5f);
color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index 0910bf3a9f..2f25b8b015 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -103,9 +103,9 @@ void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) {
VSG::rasterizer->begin_frame(frame_step);
- VSG::scene->update_dirty_instances(); //update scene stuff
+ VSG::scene_render->update(); //update scenes stuff before updating instances
- VSG::scene_render->update();
+ VSG::scene->update_dirty_instances(); //update scene stuff
VSG::viewport->draw_viewports();
VSG::scene->render_probes();
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index bef82a7da4..be19a935e9 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -313,7 +313,6 @@ public:
BIND2(light_set_use_gi, RID, bool)
BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
- BIND2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
BIND2(light_directional_set_blend_splits, RID, bool)
@@ -489,6 +488,8 @@ public:
//from now on, calls forwarded to this singleton
#define BINDBASE VSG::scene_render
+ BIND1(directional_shadow_atlas_set_size, int)
+
/* SKY API */
BIND0R(RID, sky_create)
@@ -535,7 +536,6 @@ public:
BIND2(scenario_set_debug, RID, ScenarioDebugMode)
BIND2(scenario_set_environment, RID, RID)
- BIND3(scenario_set_reflection_atlas_size, RID, int, int)
BIND2(scenario_set_fallback_environment, RID, RID)
/* INSTANCING API */
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index ae95fe386d..d060043b40 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -268,7 +268,6 @@ 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;
}
@@ -294,14 +293,6 @@ 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_size, int p_subdiv) {
-
- Scenario *scenario = scenario_owner.getornull(p_scenario);
- ERR_FAIL_COND(!scenario);
- VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_size);
- VSG::scene_render->reflection_atlas_set_subdivision(scenario->reflection_atlas, p_subdiv);
-}
-
/* INSTANCING API */
void VisualServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) {
@@ -360,11 +351,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
instance->octree_id = 0;
}
- if (instance->custom_data) {
- VSG::scene_render->instance_free_custom_data(instance);
- instance->custom_data = nullptr;
- }
-
switch (instance->base_type) {
case VS::INSTANCE_LIGHT: {
@@ -494,8 +480,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
VSG::storage->base_update_dependency(p_base, instance);
-
- VSG::scene_render->instance_create_custom_data(instance);
}
_instance_queue_update(instance, true, true);
@@ -527,8 +511,6 @@ 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: {
@@ -710,10 +692,6 @@ void VisualServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap
lightmap_capture->users.insert(instance);
instance->lightmap = p_lightmap;
}
-
- if (instance->custom_data) {
- VSG::scene_render->instance_custom_data_update_lightmap(instance);
- }
}
void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
@@ -943,10 +921,6 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
p_instance->transformed_aabb = new_aabb;
- if (p_instance->custom_data) {
- VSG::scene_render->instance_custom_data_update_transform(p_instance);
- }
-
if (!p_instance->scenario) {
return;
@@ -1614,12 +1588,12 @@ bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
//using this one ensures that raster deferred will have it
static const Vector3 view_normals[6] = {
- Vector3(-1, 0, 0),
Vector3(+1, 0, 0),
+ Vector3(-1, 0, 0),
Vector3(0, -1, 0),
Vector3(0, +1, 0),
- Vector3(0, 0, -1),
- Vector3(0, 0, +1)
+ Vector3(0, 0, +1),
+ Vector3(0, 0, -1)
};
static const Vector3 view_up[6] = {
Vector3(0, -1, 0),
@@ -1920,10 +1894,8 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
reflection_probe->reflection_dirty = false;
}
- 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++;
- }
+ reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance;
+ reflection_probe_cull_count++;
}
}
}
@@ -1970,10 +1942,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->lighting_dirty = false;
-
- if (ins->custom_data) {
- VSG::scene_render->instance_custom_data_update_lights(ins);
- }
}
if (geom->reflection_dirty) {
@@ -1989,10 +1957,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->reflection_dirty = false;
-
- if (ins->custom_data) {
- VSG::scene_render->instance_custom_data_update_reflection_probes(ins);
- }
}
if (geom->gi_probes_dirty) {
@@ -2008,10 +1972,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
geom->gi_probes_dirty = false;
-
- if (ins->custom_data) {
- VSG::scene_render->instance_custom_data_update_gi_probes(ins);
- }
}
ins->depth = near_plane.distance_to(ins->transform.origin);
@@ -2188,7 +2148,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, scenario->reflection_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, p_reflection_probe_pass);
}
void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
@@ -2202,7 +2162,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, scenario->reflection_atlas, RID(), 0);
+ VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, environment, p_shadow_atlas, RID(), 0);
#endif
}
@@ -2216,9 +2176,7 @@ bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int
if (p_step == 0) {
- if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
- return true; //sorry, all full :(
- }
+ VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance);
}
if (p_step >= 0 && p_step < 6) {
@@ -3507,7 +3465,6 @@ 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 ad0c1caff3..0f73f42153 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -115,7 +115,6 @@ public:
RID environment;
RID fallback_environment;
RID reflection_probe_shadow_atlas;
- RID reflection_atlas;
SelfList<Instance>::List instances;
@@ -132,7 +131,6 @@ 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_size, int p_subdiv);
/* INSTANCING API */
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index ac4b5c3ecb..d8cd6771c1 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -240,7 +240,6 @@ public:
FUNC2(light_set_use_gi, RID, bool)
FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
- FUNC2(light_omni_set_shadow_detail, RID, LightOmniShadowDetail)
FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
FUNC2(light_directional_set_blend_splits, RID, bool)
@@ -404,6 +403,8 @@ public:
FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
+ FUNC1(directional_shadow_atlas_set_size, int)
+
/* SKY API */
FUNCRID(sky)
@@ -447,7 +448,6 @@ public:
FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
FUNC2(scenario_set_environment, RID, RID)
- FUNC3(scenario_set_reflection_atlas_size, RID, int, int)
FUNC2(scenario_set_fallback_environment, RID, RID)
/* INSTANCING API */