summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd')
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_forward.cpp1461
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_forward.h396
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp55
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h55
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp187
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h63
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/shaders/giprobe.glsl11
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward.glsl91
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl77
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog.glsl21
14 files changed, 1518 insertions, 921 deletions
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index fb9c114ade..be2552bd32 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -154,12 +154,9 @@ void RendererCompositorRD::initialize() {
}
}
-ThreadWorkPool RendererCompositorRD::thread_work_pool;
uint64_t RendererCompositorRD::frame = 1;
void RendererCompositorRD::finalize() {
- thread_work_pool.finish();
-
memdelete(scene);
memdelete(canvas);
memdelete(storage);
@@ -174,7 +171,6 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
singleton = this;
- thread_work_pool.init();
time = 0;
storage = memnew(RendererStorageRD);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index e1995872af..cb85fc79e0 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -90,8 +90,6 @@ public:
virtual bool is_low_end() const { return false; }
- static ThreadWorkPool thread_work_pool;
-
static RendererCompositorRD *singleton;
RendererCompositorRD();
~RendererCompositorRD() {}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
index 6881d7913f..c0939f23ef 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
@@ -806,252 +806,89 @@ bool RendererSceneRenderForward::free(RID p_rid) {
return false;
}
-void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi, bool p_has_opaque_gi) {
- uint32_t lightmap_captures_used = 0;
-
- for (int i = 0; i < p_element_count; i++) {
- const RenderList::Element *e = p_elements[i];
- InstanceData &id = scene_state.instances[i];
- bool store_transform = true;
- id.flags = 0;
- id.mask = e->instance->layer_mask;
- id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0;
-
- if (e->instance->base_type == RS::INSTANCE_MULTIMESH) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- uint32_t stride;
- if (storage->multimesh_get_transform_format(e->instance->base) == RS::MULTIMESH_TRANSFORM_2D) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
- stride = 2;
- } else {
- stride = 3;
- }
- if (storage->multimesh_uses_colors(e->instance->base)) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
- stride += 1;
- }
- if (storage->multimesh_uses_custom_data(e->instance->base)) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
- stride += 1;
- }
-
- id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
- } else if (e->instance->base_type == RS::INSTANCE_PARTICLES) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- uint32_t stride;
- if (false) { // 2D particles
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
- stride = 2;
- } else {
- stride = 3;
- }
-
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
- stride += 1;
-
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
- stride += 1;
-
- id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
-
- if (!storage->particles_is_using_local_coords(e->instance->base)) {
- store_transform = false;
- }
-
- } else if (e->instance->base_type == RS::INSTANCE_MESH) {
- if (e->instance->skeleton.is_valid()) {
- id.flags |= INSTANCE_DATA_FLAG_SKELETON;
- }
- }
-
- if (store_transform) {
- RendererStorageRD::store_transform(e->instance->transform, id.transform);
- RendererStorageRD::store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
- } else {
- RendererStorageRD::store_transform(Transform(), id.transform);
- RendererStorageRD::store_transform(Transform(), id.normal_transform);
- }
-
- if (p_for_depth) {
- id.gi_offset = 0xFFFFFFFF;
- continue;
- }
-
- if (e->instance->lightmap) {
- int32_t lightmap_index = storage->lightmap_get_array_index(e->instance->lightmap->base);
- if (lightmap_index >= 0) {
- id.gi_offset = lightmap_index;
- id.gi_offset |= e->instance->lightmap_slice_index << 12;
- id.gi_offset |= e->instance->lightmap_cull_index << 20;
- id.lightmap_uv_scale[0] = e->instance->lightmap_uv_scale.position.x;
- id.lightmap_uv_scale[1] = e->instance->lightmap_uv_scale.position.y;
- id.lightmap_uv_scale[2] = e->instance->lightmap_uv_scale.size.width;
- id.lightmap_uv_scale[3] = e->instance->lightmap_uv_scale.size.height;
- id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP;
- if (storage->lightmap_uses_spherical_harmonics(e->instance->lightmap->base)) {
- id.flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP;
- }
- } else {
- id.gi_offset = 0xFFFFFFFF;
- }
- } else if (!e->instance->lightmap_sh.is_empty()) {
- if (lightmap_captures_used < scene_state.max_lightmap_captures) {
- const Color *src_capture = e->instance->lightmap_sh.ptr();
- LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used];
- for (int j = 0; j < 9; j++) {
- lcd.sh[j * 4 + 0] = src_capture[j].r;
- lcd.sh[j * 4 + 1] = src_capture[j].g;
- lcd.sh[j * 4 + 2] = src_capture[j].b;
- lcd.sh[j * 4 + 3] = src_capture[j].a;
- }
- id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE;
- id.gi_offset = lightmap_captures_used;
- lightmap_captures_used++;
- }
-
- } else {
- if (p_has_opaque_gi) {
- id.flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;
- }
-
- if (!low_end && !e->instance->gi_probe_instances.is_empty()) {
- uint32_t written = 0;
- for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) {
- RID probe = e->instance->gi_probe_instances[j];
-
- uint32_t index = gi_probe_instance_get_render_index(probe);
-
- if (written == 0) {
- id.gi_offset = index;
- id.flags |= INSTANCE_DATA_FLAG_USE_GIPROBE;
- written = 1;
- } else {
- id.gi_offset = index << 16;
- written = 2;
- break;
- }
- }
- if (written == 0) {
- id.gi_offset = 0xFFFFFFFF;
- } else if (written == 1) {
- id.gi_offset |= 0xFFFF0000;
- }
- } else {
- if (p_has_sdfgi && (e->instance->baked_light || e->instance->dynamic_gi)) {
- id.flags |= INSTANCE_DATA_FLAG_USE_SDFGI;
- }
- id.gi_offset = 0xFFFFFFFF;
- }
- }
- }
-
- RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true);
- if (lightmap_captures_used) {
- RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true);
- }
-}
-
/// RENDERING ///
-void RendererSceneRenderForward::_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, RID p_render_pass_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+template <RendererSceneRenderForward::PassMode p_pass_mode>
+void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
//global scope bindings
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, SCENE_UNIFORM_SET);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_render_pass_uniform_set, RENDER_PASS_UNIFORM_SET);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_params->render_pass_uniform_set, RENDER_PASS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET);
- MaterialData *prev_material = nullptr;
+ RID prev_material_uniform_set;
RID prev_vertex_array_rd;
RID prev_index_array_rd;
RID prev_pipeline_rd;
RID prev_xforms_uniform_set;
- PushConstant push_constant;
- zeromem(&push_constant, sizeof(PushConstant));
- push_constant.bake_uv2_offset[0] = p_uv_offset.x;
- push_constant.bake_uv2_offset[1] = p_uv_offset.y;
+ bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP);
+
+ float old_offset[2] = { 0, 0 };
- for (int i = 0; i < p_element_count; i++) {
- const RenderList::Element *e = p_elements[i];
+ for (uint32_t i = p_from_element; i < p_to_element; i++) {
+ const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
- MaterialData *material = e->material;
- ShaderData *shader = material->shader_data;
- RID xforms_uniform_set;
+ RID material_uniform_set;
+ ShaderData *shader;
+ void *mesh_surface;
+
+ if (shadow_pass) {
+ material_uniform_set = surf->material_uniform_set_shadow;
+ shader = surf->shader_shadow;
+ mesh_surface = surf->surface_shadow;
+
+ } else {
+ material_uniform_set = surf->material_uniform_set;
+ shader = surf->shader;
+ mesh_surface = surf->surface;
+ }
+
+ if (!mesh_surface) {
+ continue;
+ }
+
+ if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
+ old_offset[0] = surf->owner->push_constant.lightmap_uv_scale[0];
+ old_offset[1] = surf->owner->push_constant.lightmap_uv_scale[1];
+ surf->owner->push_constant.lightmap_uv_scale[0] = p_params->uv_offset.x;
+ surf->owner->push_constant.lightmap_uv_scale[1] = p_params->uv_offset.y;
+ }
//find cull variant
ShaderData::CullVariant cull_variant;
- if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) {
+ if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL || p_params->pass_mode == PASS_MODE_SDF || ((p_params->pass_mode == PASS_MODE_SHADOW || p_params->pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {
cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
} else {
- bool mirror = e->instance->mirror;
- if (p_reverse_cull) {
+ bool mirror = surf->owner->mirror;
+ if (p_params->reverse_cull) {
mirror = !mirror;
}
cull_variant = mirror ? ShaderData::CULL_VARIANT_REVERSED : ShaderData::CULL_VARIANT_NORMAL;
}
- //find primitive and vertex format
- RS::PrimitiveType primitive;
- void *mesh_surface = nullptr;
-
- switch (e->instance->base_type) {
- case RS::INSTANCE_MESH: {
- mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index);
-
- primitive = storage->mesh_surface_get_primitive(mesh_surface);
- if (e->instance->skeleton.is_valid()) {
- xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET);
- }
- } break;
- case RS::INSTANCE_MULTIMESH: {
- RID mesh = storage->multimesh_get_mesh(e->instance->base);
- ERR_CONTINUE(!mesh.is_valid()); //should be a bug
-
- mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index);
-
- primitive = storage->mesh_surface_get_primitive(mesh_surface);
-
- xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
-
- } break;
- case RS::INSTANCE_IMMEDIATE: {
- ERR_CONTINUE(true); //should be a bug
- } break;
- case RS::INSTANCE_PARTICLES: {
- RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16);
- ERR_CONTINUE(!mesh.is_valid()); //should be a bug
-
- mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index & 0xFFFF);
-
- primitive = storage->mesh_surface_get_primitive(mesh_surface);
-
- xforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
-
- } break;
- default: {
- ERR_CONTINUE(true); //should be a bug
- }
- }
+ RS::PrimitiveType primitive = surf->primitive;
+ RID xforms_uniform_set = surf->owner->transforms_uniform_set;
ShaderVersion shader_version = SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
- switch (p_pass_mode) {
+ switch (p_params->pass_mode) {
case PASS_MODE_COLOR:
case PASS_MODE_COLOR_TRANSPARENT: {
- if (e->uses_lightmap) {
+ if (surf->sort.uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS;
- } else if (e->uses_forward_gi) {
+ } else if (surf->sort.uses_forward_gi) {
shader_version = SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI;
} else {
shader_version = SHADER_VERSION_COLOR_PASS;
}
} break;
case PASS_MODE_COLOR_SPECULAR: {
- if (e->uses_lightmap) {
+ if (surf->sort.uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
} else {
shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
@@ -1086,40 +923,37 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
RID vertex_array_rd;
RID index_array_rd;
- if (mesh_surface) {
- if (e->instance->mesh_instance.is_valid()) { //skeleton and blend shape
- storage->mesh_instance_surface_get_vertex_arrays_and_format(e->instance->mesh_instance, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
- } else {
- storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
- }
-
- if (p_screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) {
- Vector3 support_min = e->instance->transformed_aabb.get_support(-p_lod_plane.normal);
- Vector3 support_max = e->instance->transformed_aabb.get_support(p_lod_plane.normal);
-
- float distance_min = p_lod_plane.distance_to(support_min);
- float distance_max = p_lod_plane.distance_to(support_max);
+ //skeleton and blend shape
+ if (surf->owner->mesh_instance.is_valid()) {
+ storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ } else {
+ storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ }
- float distance = 0.0;
+ if (p_params->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) {
+ //lod
+ Vector3 support_min = surf->owner->transformed_aabb.get_support(-p_params->lod_plane.normal);
+ Vector3 support_max = surf->owner->transformed_aabb.get_support(p_params->lod_plane.normal);
- if (distance_min * distance_max < 0.0) {
- //crossing plane
- distance = 0.0;
- } else if (distance_min >= 0.0) {
- distance = distance_min;
- } else if (distance_max <= 0.0) {
- distance = -distance_max;
- }
+ float distance_min = p_params->lod_plane.distance_to(support_min);
+ float distance_max = p_params->lod_plane.distance_to(support_max);
- Vector3 model_scale_vec = e->instance->transform.basis.get_scale_abs();
+ float distance = 0.0;
- float model_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
+ if (distance_min * distance_max < 0.0) {
+ //crossing plane
+ distance = 0.0;
+ } else if (distance_min >= 0.0) {
+ distance = distance_min;
+ } else if (distance_max <= 0.0) {
+ distance = -distance_max;
+ }
- index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, model_scale * e->instance->lod_bias, distance * p_lod_distance_multiplier, p_screen_lod_threshold);
+ index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, surf->owner->lod_model_scale * surf->owner->lod_bias, distance * p_params->lod_distance_multiplier, p_params->screen_lod_threshold);
- } else {
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface);
- }
+ } else {
+ //no lod
+ index_array_rd = storage->mesh_surface_get_index_array(mesh_surface);
}
if (prev_vertex_array_rd != vertex_array_rd) {
@@ -1134,7 +968,7 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
prev_index_array_rd = index_array_rd;
}
- RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_force_wireframe);
+ RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe);
if (pipeline_rd != prev_pipeline_rd) {
// checking with prev shader does not make so much sense, as
@@ -1148,39 +982,89 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
prev_xforms_uniform_set = xforms_uniform_set;
}
- if (material != prev_material) {
+ if (material_uniform_set != prev_material_uniform_set) {
//update uniform set
- if (material->uniform_set.is_valid()) {
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, MATERIAL_UNIFORM_SET);
+ if (material_uniform_set.is_valid()) {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET);
}
- prev_material = material;
+ prev_material_uniform_set = material_uniform_set;
}
- push_constant.index = i;
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &surf->owner->push_constant, sizeof(GeometryInstanceForward::PushConstant));
- switch (e->instance->base_type) {
- case RS::INSTANCE_MESH: {
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid());
- } break;
- case RS::INSTANCE_MULTIMESH: {
- uint32_t instances = storage->multimesh_get_instances_to_draw(e->instance->base);
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances);
- } break;
- case RS::INSTANCE_IMMEDIATE: {
- } break;
- case RS::INSTANCE_PARTICLES: {
- uint32_t instances = storage->particles_get_amount(e->instance->base);
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances);
- } break;
- default: {
- ERR_CONTINUE(true); //should be a bug
- }
+ RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), surf->owner->instance_count);
+
+ if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
+ surf->owner->push_constant.lightmap_uv_scale[0] = old_offset[0];
+ surf->owner->push_constant.lightmap_uv_scale[1] = old_offset[1];
}
}
}
+void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
+ //use template for faster performance (pass mode comparisons are inlined)
+
+ switch (p_params->pass_mode) {
+ case PASS_MODE_COLOR: {
+ _render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_COLOR_SPECULAR: {
+ _render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_COLOR_TRANSPARENT: {
+ _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_SHADOW: {
+ _render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_SHADOW_DP: {
+ _render_list_template<PASS_MODE_SHADOW_DP>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_DEPTH: {
+ _render_list_template<PASS_MODE_DEPTH>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
+ _render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: {
+ _render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_DEPTH_MATERIAL: {
+ _render_list_template<PASS_MODE_DEPTH_MATERIAL>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_SDF: {
+ _render_list_template<PASS_MODE_SDF>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ }
+}
+
+void RendererSceneRenderForward::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
+ uint32_t render_total = p_params->element_count;
+ uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t render_from = p_thread * render_total / total_threads;
+ uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads);
+ _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
+}
+
+void RendererSceneRenderForward::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
+ RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer);
+ p_params->framebuffer_format = fb_format;
+
+ if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time
+ //multi threaded
+ thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
+ RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RendererSceneRenderForward::_render_list_thread_function, p_params);
+ RD::get_singleton()->draw_list_end();
+ } else {
+ //single threaded
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
+ _render_list(draw_list, fb_format, p_params, 0, p_params->element_count);
+ RD::get_singleton()->draw_list_end();
+ }
+}
+
void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) {
//CameraMatrix projection = p_cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
@@ -1413,128 +1297,7 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren
RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
}
-void RendererSceneRenderForward::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) {
- RID m_src;
-
- m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
-
- if (unlikely(get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_DISABLED)) {
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
- m_src = overdraw_material;
- } else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING) {
- m_src = default_material;
- }
- }
-
- MaterialData *material = nullptr;
-
- if (m_src.is_valid()) {
- material = (MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
- m_src = default_material;
- }
-
- ERR_FAIL_COND(!material);
-
- _add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index, p_using_sdfgi);
-
- while (material->next_pass.is_valid()) {
- material = (MaterialData *)storage->material_get_data(material->next_pass, RendererStorageRD::SHADER_TYPE_3D);
- if (!material || !material->shader_data->valid) {
- break;
- }
- _add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index, p_using_sdfgi);
- }
-}
-
-void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) {
- 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);
- bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
- bool has_alpha = has_base_alpha || has_blend_alpha;
-
- if (p_material->shader_data->uses_sss) {
- scene_state.used_sss = true;
- }
-
- if (p_material->shader_data->uses_screen_texture) {
- scene_state.used_screen_texture = true;
- }
-
- if (p_material->shader_data->uses_depth_texture) {
- scene_state.used_depth_texture = true;
- }
-
- if (p_material->shader_data->uses_normal_texture) {
- scene_state.used_normal_texture = true;
- }
-
- if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) {
- if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
- //conditions in which no depth pass should be processed
- return;
- }
-
- if ((p_pass_mode != PASS_MODE_DEPTH_MATERIAL && p_pass_mode != PASS_MODE_SDF) && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) {
- //shader does not use discard and does not write a vertex position, use generic material
- if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_DEPTH) {
- p_material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
- } else if ((p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) {
- p_material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
- }
- }
-
- has_alpha = false;
- }
-
- has_alpha = has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED;
-
- RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
-
- if (!e) {
- return;
- }
-
- e->instance = p_instance;
- e->material = p_material;
- e->surface_index = p_surface;
- e->sort_key = 0;
-
- if (e->material->last_pass != render_pass) {
- if (!RD::get_singleton()->uniform_set_is_valid(e->material->uniform_set)) {
- //uniform set no longer valid, probably a texture changed
- storage->material_force_update_textures(p_material_rid, RendererStorageRD::SHADER_TYPE_3D);
- }
- e->material->last_pass = render_pass;
- e->material->index = scene_state.current_material_index++;
- if (e->material->shader_data->last_pass != render_pass) {
- e->material->shader_data->last_pass = scene_state.current_material_index++;
- 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 == RS::INSTANCE_MULTIMESH;
- e->uses_lightmap = e->instance->lightmap != nullptr || !e->instance->lightmap_sh.is_empty();
- e->uses_forward_gi = has_alpha && (e->instance->gi_probe_instances.size() || p_using_sdfgi);
- e->shader_index = e->shader_index;
- e->depth_layer = e->instance->depth_layer;
- e->priority = p_material->priority;
-
- if (p_material->shader_data->uses_time) {
- RenderingServerDefault::redraw_request();
- }
-}
-
-void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi) {
- scene_state.current_shader_index = 0;
- scene_state.current_material_index = 0;
+void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi) {
scene_state.used_sss = false;
scene_state.used_screen_texture = false;
scene_state.used_normal_texture = false;
@@ -1543,125 +1306,184 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase
Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
near_plane.d += p_cam_projection.get_z_near();
float z_max = p_cam_projection.get_z_far() - p_cam_projection.get_z_near();
+ uint32_t lightmap_captures_used = 0;
- uint32_t geometry_index = 0;
+ _update_dirty_geometry_instances();
+ render_list.clear();
//fill list
for (int i = 0; i < (int)p_instances.size(); i++) {
- InstanceBase *inst = p_instances[i];
+ GeometryInstanceForward *inst = static_cast<GeometryInstanceForward *>(p_instances[i]);
- inst->depth = near_plane.distance_to(inst->transform.origin);
- inst->depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
+ Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal);
+ inst->depth = near_plane.distance_to(support_min);
+ uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
- //add geometry for drawing
- switch (inst->base_type) {
- case RS::INSTANCE_MESH: {
- const RID *materials = nullptr;
- uint32_t surface_count;
-
- materials = storage->mesh_get_surface_count_and_materials(inst->base, surface_count);
- if (!materials) {
- continue; //nothing to do
- }
+ uint32_t flags = inst->base_flags; //fill flags if appropriate
- const RID *inst_materials = inst->materials.ptr();
+ bool uses_lightmap = false;
+ bool uses_gi = false;
- for (uint32_t j = 0; j < surface_count; j++) {
- RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
+ if (p_pass_mode == PASS_MODE_COLOR) {
+ //setup GI
- 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, p_using_sdfgi);
+ if (inst->lightmap_instance.is_valid()) {
+ int32_t lightmap_cull_index = -1;
+ for (uint32_t j = 0; j < scene_state.lightmaps_used; j++) {
+ if (scene_state.lightmap_ids[j] == inst->lightmap_instance) {
+ lightmap_cull_index = j;
+ break;
+ }
}
-
- //mesh->last_pass=frame;
-
- } break;
-
- case RS::INSTANCE_MULTIMESH: {
- if (storage->multimesh_get_instances_to_draw(inst->base) == 0) {
- //not visible, 0 instances
- continue;
+ if (lightmap_cull_index >= 0) {
+ inst->push_constant.gi_offset &= 0xFFFF;
+ inst->push_constant.gi_offset |= lightmap_cull_index;
+ flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP;
+ if (scene_state.lightmap_has_sh[lightmap_cull_index]) {
+ flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP;
+ }
+ uses_lightmap = true;
+ } else {
+ inst->push_constant.gi_offset = 0xFFFFFFFF;
}
- RID mesh = storage->multimesh_get_mesh(inst->base);
- if (!mesh.is_valid()) {
- continue;
+ } else if (inst->lightmap_sh) {
+ if (lightmap_captures_used < scene_state.max_lightmap_captures) {
+ const Color *src_capture = inst->lightmap_sh->sh;
+ LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used];
+ for (int j = 0; j < 9; j++) {
+ lcd.sh[j * 4 + 0] = src_capture[j].r;
+ lcd.sh[j * 4 + 1] = src_capture[j].g;
+ lcd.sh[j * 4 + 2] = src_capture[j].b;
+ lcd.sh[j * 4 + 3] = src_capture[j].a;
+ }
+ flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE;
+ inst->push_constant.gi_offset = lightmap_captures_used;
+ lightmap_captures_used++;
+ uses_lightmap = true;
}
- const RID *materials = nullptr;
- uint32_t surface_count;
-
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
- if (!materials) {
- continue; //nothing to do
+ } else if (!low_end) {
+ if (p_using_opaque_gi) {
+ flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;
}
- for (uint32_t j = 0; j < surface_count; j++) {
- uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(mesh, j, render_pass, &geometry_index);
- _add_geometry(inst, j, materials[j], p_pass_mode, surface_index, p_using_sdfgi);
- }
+ if (inst->gi_probes[0].is_valid()) {
+ uint32_t probe0_index = 0xFFFF;
+ uint32_t probe1_index = 0xFFFF;
- } break;
-#if 0
- case RS::INSTANCE_IMMEDIATE: {
- RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
- ERR_CONTINUE(!immediate);
+ for (uint32_t j = 0; j < scene_state.giprobes_used; j++) {
+ if (scene_state.giprobe_ids[j] == inst->gi_probes[0]) {
+ probe0_index = j;
+ } else if (scene_state.giprobe_ids[j] == inst->gi_probes[1]) {
+ probe1_index = j;
+ }
+ }
- _add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass);
+ if (probe0_index == 0xFFFF && probe1_index != 0xFFFF) {
+ //0 must always exist if a probe exists
+ SWAP(probe0_index, probe1_index);
+ }
- } break;
-#endif
- case RS::INSTANCE_PARTICLES: {
- int draw_passes = storage->particles_get_draw_passes(inst->base);
+ inst->push_constant.gi_offset = probe0_index | (probe1_index << 16);
+ uses_gi = true;
+ } else {
+ if (p_using_sdfgi && inst->can_sdfgi) {
+ flags |= INSTANCE_DATA_FLAG_USE_SDFGI;
+ uses_gi = true;
+ }
+ inst->push_constant.gi_offset = 0xFFFFFFFF;
+ }
+ }
+ }
+ inst->push_constant.flags = flags;
- for (int j = 0; j < draw_passes; j++) {
- RID mesh = storage->particles_get_draw_pass_mesh(inst->base, j);
- if (!mesh.is_valid())
- continue;
+ GeometryInstanceSurfaceDataCache *surf = inst->surface_caches;
- const RID *materials = nullptr;
- uint32_t surface_count;
+ while (surf) {
+ surf->sort.uses_forward_gi = 0;
+ surf->sort.uses_lightmap = 0;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
- if (!materials) {
- continue; //nothing to do
+ if (p_pass_mode == PASS_MODE_COLOR) {
+ if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ render_list.add_element(surf);
+ }
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA) {
+ render_list.add_alpha_element(surf);
+ if (uses_gi) {
+ surf->sort.uses_forward_gi = 1;
}
+ }
- for (uint32_t k = 0; k < surface_count; k++) {
- uint32_t surface_index = storage->mesh_surface_get_particles_render_pass_index(mesh, j, render_pass, &geometry_index);
- _add_geometry(inst, (j << 16) | k, materials[j], p_pass_mode, surface_index, p_using_sdfgi);
- }
+ if (uses_lightmap) {
+ surf->sort.uses_lightmap = 1;
}
- } break;
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) {
+ scene_state.used_sss = true;
+ }
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE) {
+ scene_state.used_screen_texture = true;
+ }
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE) {
+ scene_state.used_normal_texture = true;
+ }
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
+ scene_state.used_depth_texture = true;
+ }
- default: {
+ } else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) {
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) {
+ render_list.add_element(surf);
+ }
+ } else {
+ if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ render_list.add_element(surf);
+ }
}
+
+ surf->sort.depth_layer = depth_layer;
+
+ surf = surf->next;
}
}
+
+ if (lightmap_captures_used) {
+ RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true);
+ }
}
-void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform) {
- uint32_t lightmaps_used = 0;
+void RendererSceneRenderForward::_setup_giprobes(const PagedArray<RID> &p_giprobes) {
+ scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES));
+ for (uint32_t i = 0; i < scene_state.giprobes_used; i++) {
+ scene_state.giprobe_ids[i] = p_giprobes[i];
+ }
+}
+
+void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) {
+ scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
if (i >= (int)scene_state.max_lightmaps) {
break;
}
- InstanceBase *lm = p_lightmaps[i];
- Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis;
+ RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]);
+
+ Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
- lm->lightmap_cull_index = i;
- lightmaps_used++;
+ scene_state.lightmap_ids[i] = p_lightmaps[i];
+ scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap);
+
+ scene_state.lightmaps_used++;
}
- if (lightmaps_used > 0) {
- RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * lightmaps_used, scene_state.lightmaps, true);
+ if (scene_state.lightmaps_used > 0) {
+ RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps, true);
}
}
-void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
RenderBufferDataForward *render_buffer = nullptr;
if (p_render_buffer.is_valid()) {
render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
@@ -1784,12 +1606,12 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
_setup_lightmaps(p_lightmaps, p_cam_transform);
+ _setup_giprobes(p_gi_probes);
_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
- render_list.clear();
- _fill_render_list(p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi);
+ _fill_render_list(p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi, using_sdfgi || using_giprobe);
bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
@@ -1873,8 +1695,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, false, false, using_sdfgi || using_giprobe);
-
bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION;
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
@@ -1885,12 +1705,11 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
if (depth_pre_pass) { //depth pre pass
RENDER_TIMESTAMP("Render Depth Pre-Pass");
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_list_end();
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ _render_list_with_threads(&render_list_params, depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
RENDER_TIMESTAMP("Resolve Depth Pre-Pass");
@@ -1917,7 +1736,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
RENDER_TIMESTAMP("Render Opaque Pass");
- RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes);
+ RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes, p_lightmaps);
bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;
bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss;
@@ -1938,13 +1757,13 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_list_end();
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+
+ _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
- draw_list = RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
+ RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
RD::get_singleton()->draw_list_end();
}
}
@@ -2023,12 +1842,9 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
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, false, using_sdfgi);
-
{
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
- _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, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_list_end();
+ RenderListParameters render_list_params(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
@@ -2036,7 +1852,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
}
-void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, 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, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, 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, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
RENDER_TIMESTAMP("Setup Rendering Shadow");
_update_render_base_uniform_set();
@@ -2051,29 +1867,24 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedAr
p_screen_lod_threshold = 0.0;
}
- render_list.clear();
-
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
_fill_render_list(p_instances, pass_mode, p_projection, p_transform);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Shadow");
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
-
{
//regular forward for now
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
- _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, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_list_end();
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
+ _render_list_with_threads(&render_list_params, p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
}
}
-void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup Render Collider Heightfield");
_update_render_base_uniform_set();
@@ -2084,29 +1895,24 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,
_setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_cam_projection.get_z_far(), false, false);
- render_list.clear();
-
PassMode pass_mode = PASS_MODE_SHADOW;
_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Collider Heightield");
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
-
{
//regular forward for now
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_fb), render_list.elements, render_list.element_count, false, pass_mode, true, rp_uniform_set);
- RD::get_singleton()->draw_list_end();
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, pass_mode, true, rp_uniform_set);
+ _render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
}
}
-void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering Material");
_update_render_base_uniform_set();
@@ -2118,20 +1924,17 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
_setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
- render_list.clear();
-
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Material");
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
-
{
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -2140,12 +1943,12 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
clear.push_back(Color(0, 0, 0, 0));
clear.push_back(Color(0, 0, 0, 0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count);
RD::get_singleton()->draw_list_end();
}
}
-void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
_update_render_base_uniform_set();
@@ -2157,20 +1960,17 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p
_setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
- render_list.clear();
-
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
_fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Material");
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
-
{
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, true);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -2198,15 +1998,17 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p
Vector2 ofs = uv_offsets[i];
ofs.x /= p_region.size.width;
ofs.y /= p_region.size.height;
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, true, ofs); //first wireframe, for pseudo conservative
+ render_list_params.uv_offset = ofs;
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); //first wireframe, for pseudo conservative
}
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false); //second regular triangles
+ render_list_params.uv_offset = Vector2();
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); //second regular triangles
RD::get_singleton()->draw_list_end();
}
}
-void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
RENDER_TIMESTAMP("Render SDFGI");
_update_render_base_uniform_set();
@@ -2215,12 +2017,10 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto
ERR_FAIL_COND(!render_buffer);
render_pass++;
- render_list.clear();
PassMode pass_mode = PASS_MODE_SDF;
_fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);
@@ -2281,9 +2081,8 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
}
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(E->get()), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false); //second regular triangles
- RD::get_singleton()->draw_list_end();
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false);
+ _render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
}
}
@@ -2340,13 +2139,6 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
u.ids.push_back(scene_state.uniform_buffer);
uniforms.push_back(u);
}
- {
- RD::Uniform u;
- u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(scene_state.instance_buffer);
- uniforms.push_back(u);
- }
{
RD::Uniform u;
@@ -2380,20 +2172,13 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.binding = 11;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids = storage->lightmap_array_get_textures();
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_capture_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 13;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture();
u.ids.push_back(decal_atlas);
@@ -2401,7 +2186,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 14;
+ u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture_srgb();
u.ids.push_back(decal_atlas);
@@ -2409,7 +2194,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 15;
+ u.binding = 14;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_decal_buffer());
uniforms.push_back(u);
@@ -2417,14 +2202,14 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
{
RD::Uniform u;
- u.binding = 16;
+ u.binding = 15;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.push_back(get_cluster_builder_texture());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 17;
+ u.binding = 16;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_cluster_builder_indices_buffer());
uniforms.push_back(u);
@@ -2432,7 +2217,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
{
RD::Uniform u;
- u.binding = 18;
+ u.binding = 17;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (directional_shadow_get_texture().is_valid()) {
u.ids.push_back(directional_shadow_get_texture());
@@ -2445,7 +2230,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 19;
+ u.binding = 18;
u.ids.push_back(storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2453,7 +2238,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
if (!low_end) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 20;
+ u.binding = 19;
u.ids.push_back(sdfgi_get_ubo());
uniforms.push_back(u);
}
@@ -2462,7 +2247,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
}
-RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes) {
+RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps) {
if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
RD::get_singleton()->free(render_pass_uniform_set);
}
@@ -2517,11 +2302,29 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
u.ids.push_back(texture);
uniforms.push_back(u);
}
-
{
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.resize(scene_state.max_lightmaps);
+ RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
+ if (i < p_lightmaps.size()) {
+ RID base = lightmap_instance_get_lightmap(p_lightmaps[i]);
+ RID texture = storage->lightmap_get_texture(base);
+ RID rd_texture = storage->texture_get_rd_texture(texture);
+ u.ids.write[i] = rd_texture;
+ } else {
+ u.ids.write[i] = default_tex;
+ }
+ }
+
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_GI_PROBES);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_GI_PROBES; i++) {
@@ -2541,7 +2344,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 4;
+ u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
u.ids.push_back(texture);
@@ -2549,7 +2352,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 5;
+ u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_buffers) : RID();
RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2559,7 +2362,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
if (!low_end) {
{
RD::Uniform u;
- u.binding = 6;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL);
u.ids.push_back(texture);
@@ -2568,7 +2371,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID aot = rb ? render_buffers_get_ao_texture(p_render_buffers) : RID();
RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2578,7 +2381,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 8;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = rb && rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
u.ids.push_back(texture);
@@ -2587,7 +2390,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 9;
+ u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = rb && rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
u.ids.push_back(texture);
@@ -2595,7 +2398,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID t;
if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
@@ -2608,7 +2411,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers));
@@ -2619,14 +2422,14 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 12;
+ u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_buffers) : render_buffers_get_default_gi_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 13;
+ u.binding = 14;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID vfog = RID();
if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) {
@@ -2684,10 +2487,24 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
}
{
- // No GIProbes
+ // No Lightmaps
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.resize(scene_state.max_lightmaps);
+ RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
+ u.ids.write[i] = default_tex;
+ }
+
+ uniforms.push_back(u);
+ }
+
+ {
+ // No GIProbes
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_GI_PROBES);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_GI_PROBES; i++) {
@@ -2701,28 +2518,28 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 4;
+ u.binding = 5;
u.ids.push_back(p_albedo_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 5;
+ u.binding = 6;
u.ids.push_back(p_emission_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 6;
+ u.binding = 7;
u.ids.push_back(p_emission_aniso_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 7;
+ u.binding = 8;
u.ids.push_back(p_geom_facing_texture);
uniforms.push_back(u);
}
@@ -2765,6 +2582,534 @@ void RendererSceneRenderForward::set_time(double p_time, double p_step) {
RendererSceneRenderRD::set_time(p_time, p_step);
}
+void RendererSceneRenderForward::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ if (ginstance->dirty_list_element.in_list()) {
+ return;
+ }
+
+ //clear surface caches
+ GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+
+ while (surf) {
+ GeometryInstanceSurfaceDataCache *next = surf->next;
+ geometry_instance_surface_alloc.free(surf);
+ surf = next;
+ }
+
+ ginstance->surface_caches = nullptr;
+
+ geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+}
+
+void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+ 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);
+ bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
+ bool has_alpha = has_base_alpha || has_blend_alpha;
+
+ uint32_t flags = 0;
+
+ if (p_material->shader_data->uses_sss) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING;
+ }
+
+ if (p_material->shader_data->uses_screen_texture) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE;
+ }
+
+ if (p_material->shader_data->uses_depth_texture) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE;
+ }
+
+ if (p_material->shader_data->uses_normal_texture) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE;
+ }
+
+ if (ginstance->data->cast_double_sided_shaodows) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS;
+ }
+
+ if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) {
+ //material is only meant for alpha pass
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA;
+ if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED)) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH;
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW;
+ }
+ } else {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE;
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH;
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW;
+ }
+
+ MaterialData *material_shadow = nullptr;
+ //void *surface_shadow = nullptr;
+ if (!p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
+ material_shadow = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ } else {
+ material_shadow = p_material;
+ }
+
+ GeometryInstanceSurfaceDataCache *sdcache = geometry_instance_surface_alloc.alloc();
+
+ sdcache->flags = flags;
+
+ sdcache->shader = p_material->shader_data;
+ sdcache->material_uniform_set = p_material->uniform_set;
+ sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface);
+ sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface);
+ sdcache->surface_index = p_surface;
+
+ if (ginstance->data->dirty_dependencies) {
+ storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
+ }
+
+ //shadow
+ sdcache->shader_shadow = material_shadow->shader_data;
+ sdcache->material_uniform_set_shadow = material_shadow->uniform_set;
+ sdcache->surface_shadow = sdcache->surface; //when adding special shadow meshes, will use this
+
+ sdcache->owner = ginstance;
+
+ sdcache->next = ginstance->surface_caches;
+ ginstance->surface_caches = sdcache;
+
+ //sortkey
+
+ sdcache->sort.sort_key1 = 0;
+ sdcache->sort.sort_key2 = 0;
+
+ sdcache->sort.surface_type = ginstance->data->base_type;
+ sdcache->sort.material_id = p_material_id;
+ sdcache->sort.shader_id = p_shader_id;
+ sdcache->sort.geometry_id = p_mesh.get_local_index();
+ sdcache->sort.uses_forward_gi = ginstance->can_sdfgi;
+ sdcache->sort.priority = p_material->priority;
+}
+
+void RendererSceneRenderForward::_geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+ RID m_src;
+
+ m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
+
+ MaterialData *material = nullptr;
+
+ if (m_src.is_valid()) {
+ material = (MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (material) {
+ if (ginstance->data->dirty_dependencies) {
+ storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ }
+ } else {
+ material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ m_src = default_material;
+ }
+
+ ERR_FAIL_COND(!material);
+
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, m_src.get_local_index(), storage->material_get_shader_id(m_src), p_mesh);
+
+ while (material->next_pass.is_valid()) {
+ RID next_pass = material->next_pass;
+ material = (MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ if (!material || !material->shader_data->valid) {
+ break;
+ }
+ if (ginstance->data->dirty_dependencies) {
+ storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ }
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+ }
+}
+
+void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+
+ if (ginstance->data->dirty_dependencies) {
+ ginstance->data->dependency_tracker.update_begin();
+ }
+
+ //add geometry for drawing
+ switch (ginstance->data->base_type) {
+ case RS::INSTANCE_MESH: {
+ const RID *materials = nullptr;
+ uint32_t surface_count;
+ RID mesh = ginstance->data->base;
+
+ materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (materials) {
+ //if no materials, no surfaces.
+ const RID *inst_materials = ginstance->data->surface_materials.ptr();
+ uint32_t surf_mat_count = ginstance->data->surface_materials.size();
+
+ for (uint32_t j = 0; j < surface_count; j++) {
+ RID material = (j < surf_mat_count && inst_materials[j].is_valid()) ? inst_materials[j] : materials[j];
+ _geometry_instance_add_surface(ginstance, j, material, mesh);
+ }
+ }
+
+ ginstance->instance_count = 1;
+
+ } break;
+
+ case RS::INSTANCE_MULTIMESH: {
+ RID mesh = storage->multimesh_get_mesh(ginstance->data->base);
+ if (mesh.is_valid()) {
+ const RID *materials = nullptr;
+ uint32_t surface_count;
+
+ materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (materials) {
+ for (uint32_t j = 0; j < surface_count; j++) {
+ _geometry_instance_add_surface(ginstance, j, materials[j], mesh);
+ }
+ }
+
+ ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ }
+
+ } break;
+#if 0
+ case RS::INSTANCE_IMMEDIATE: {
+ RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
+ ERR_CONTINUE(!immediate);
+
+ _add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass);
+
+ } break;
+#endif
+ case RS::INSTANCE_PARTICLES: {
+ int draw_passes = storage->particles_get_draw_passes(ginstance->data->base);
+
+ for (int j = 0; j < draw_passes; j++) {
+ RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
+ if (!mesh.is_valid())
+ continue;
+
+ const RID *materials = nullptr;
+ uint32_t surface_count;
+
+ materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (materials) {
+ for (uint32_t k = 0; k < surface_count; k++) {
+ _geometry_instance_add_surface(ginstance, k, materials[k], mesh);
+ }
+ }
+ }
+
+ ginstance->instance_count = storage->particles_get_amount(ginstance->data->base);
+
+ } break;
+
+ default: {
+ }
+ }
+
+ //Fill push constant
+
+ ginstance->push_constant.instance_uniforms_ofs = ginstance->data->shader_parameters_offset >= 0 ? ginstance->data->shader_parameters_offset : 0;
+ ginstance->push_constant.layer_mask = ginstance->data->layer_mask;
+ ginstance->push_constant.flags = 0;
+ ginstance->push_constant.gi_offset = 0xFFFFFFFF; //disabled
+
+ bool store_transform = true;
+
+ if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
+ uint32_t stride;
+ if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
+ stride = 2;
+ } else {
+ stride = 3;
+ }
+ if (storage->multimesh_uses_colors(ginstance->data->base)) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
+ stride += 1;
+ }
+ if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
+ stride += 1;
+ }
+
+ ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
+ ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
+
+ } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
+ uint32_t stride;
+ if (false) { // 2D particles
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
+ stride = 2;
+ } else {
+ stride = 3;
+ }
+
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
+ stride += 1;
+
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
+ stride += 1;
+
+ ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
+
+ if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
+ store_transform = false;
+ }
+ ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
+
+ } else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
+ if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_SKELETON;
+ ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (ginstance->data->dirty_dependencies) {
+ storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ }
+ }
+ }
+
+ if (store_transform) {
+ RendererStorageRD::store_transform(ginstance->data->transform, ginstance->push_constant.transform);
+ } else {
+ RendererStorageRD::store_transform(Transform(), ginstance->push_constant.transform);
+ }
+
+ ginstance->can_sdfgi = false;
+
+ if (lightmap_instance_is_valid(ginstance->lightmap_instance)) {
+ ginstance->push_constant.gi_offset = ginstance->data->lightmap_slice_index << 16;
+ ginstance->push_constant.lightmap_uv_scale[0] = ginstance->data->lightmap_uv_scale.position.x;
+ ginstance->push_constant.lightmap_uv_scale[1] = ginstance->data->lightmap_uv_scale.position.y;
+ ginstance->push_constant.lightmap_uv_scale[2] = ginstance->data->lightmap_uv_scale.size.width;
+ ginstance->push_constant.lightmap_uv_scale[3] = ginstance->data->lightmap_uv_scale.size.height;
+ } else if (!low_end) {
+ if (ginstance->gi_probes[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) {
+ ginstance->can_sdfgi = true;
+ }
+ }
+
+ if (ginstance->data->dirty_dependencies) {
+ ginstance->data->dependency_tracker.update_end();
+ ginstance->data->dirty_dependencies = false;
+ }
+
+ ginstance->dirty_list_element.remove_from_list();
+}
+
+void RendererSceneRenderForward::_update_dirty_geometry_instances() {
+ while (geometry_instance_dirty_list.first()) {
+ _geometry_instance_update(geometry_instance_dirty_list.first()->self());
+ }
+}
+
+void RendererSceneRenderForward::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
+ switch (p_notification) {
+ case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
+ case RendererStorage::DEPENDENCY_CHANGED_MESH:
+ case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
+ case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
+ static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ } break;
+ case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_tracker->userdata);
+ if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
+ ginstance->instance_count = static_cast<RendererSceneRenderForward *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ }
+ } break;
+ default: {
+ //rest of notifications of no interest
+ } break;
+ }
+}
+void RendererSceneRenderForward::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
+ static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+}
+
+RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_instance_create(RID p_base) {
+ RS::InstanceType type = storage->get_base_type(p_base);
+ ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
+
+ GeometryInstanceForward *ginstance = geometry_instance_alloc.alloc();
+ ginstance->data = memnew(GeometryInstanceForward::Data);
+
+ ginstance->data->base = p_base;
+ ginstance->data->base_type = type;
+ ginstance->data->dependency_tracker.userdata = ginstance;
+ ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed;
+ ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted;
+
+ _geometry_instance_mark_dirty(ginstance);
+
+ return ginstance;
+}
+void RendererSceneRenderForward::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->skeleton = p_skeleton;
+ _geometry_instance_mark_dirty(ginstance);
+ ginstance->data->dirty_dependencies = true;
+}
+void RendererSceneRenderForward::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->material_override = p_override;
+ _geometry_instance_mark_dirty(ginstance);
+ ginstance->data->dirty_dependencies = true;
+}
+void RendererSceneRenderForward::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->surface_materials = p_materials;
+ _geometry_instance_mark_dirty(ginstance);
+ ginstance->data->dirty_dependencies = true;
+}
+void RendererSceneRenderForward::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->mesh_instance = p_mesh_instance;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ RendererStorageRD::store_transform(p_transform, ginstance->push_constant.transform);
+ ginstance->data->transform = p_transform;
+ ginstance->mirror = p_transform.basis.determinant() < 0;
+ ginstance->data->aabb = p_aabb;
+ ginstance->transformed_aabb = p_transformed_aabb;
+
+ Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
+ // handle non uniform scale here
+
+ float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
+ float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
+ ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
+
+ ginstance->lod_model_scale = max_scale;
+}
+void RendererSceneRenderForward::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->lod_bias = p_lod_bias;
+}
+void RendererSceneRenderForward::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->use_baked_light = p_enable;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->use_dynamic_gi = p_enable;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->lightmap_instance = p_lightmap_instance;
+ ginstance->data->lightmap_uv_scale = p_lightmap_uv_scale;
+ ginstance->data->lightmap_slice_index = p_lightmap_slice_index;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ if (p_sh9) {
+ if (ginstance->lightmap_sh == nullptr) {
+ ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc();
+ }
+
+ copymem(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
+ } else {
+ if (ginstance->lightmap_sh != nullptr) {
+ geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
+ ginstance->lightmap_sh = nullptr;
+ }
+ }
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->shader_parameters_offset = p_offset;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+
+ ginstance->data->cast_double_sided_shaodows = p_enable;
+ _geometry_instance_mark_dirty(ginstance);
+}
+
+void RendererSceneRenderForward::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->layer_mask = p_layer_mask;
+ ginstance->push_constant.layer_mask = p_layer_mask;
+}
+
+void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ if (ginstance->lightmap_sh != nullptr) {
+ geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
+ }
+ GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+ while (surf) {
+ GeometryInstanceSurfaceDataCache *next = surf->next;
+ geometry_instance_surface_alloc.free(surf);
+ surf = next;
+ }
+ memdelete(ginstance->data);
+ geometry_instance_alloc.free(ginstance);
+}
+
+uint32_t RendererSceneRenderForward::geometry_instance_get_pair_mask() {
+ return (1 << RS::INSTANCE_GI_PROBE);
+}
+void RendererSceneRenderForward::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
+}
+void RendererSceneRenderForward::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
+}
+void RendererSceneRenderForward::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
+}
+
+Transform RendererSceneRenderForward::geometry_instance_get_transform(GeometryInstance *p_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance);
+ ERR_FAIL_COND_V(!ginstance, Transform());
+ return ginstance->data->transform;
+}
+AABB RendererSceneRenderForward::geometry_instance_get_aabb(GeometryInstance *p_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance);
+ ERR_FAIL_COND_V(!ginstance, AABB());
+ return ginstance->data->aabb;
+}
+
+void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ if (p_gi_probe_instance_count > 0) {
+ ginstance->gi_probes[0] = p_gi_probe_instances[0];
+ } else {
+ ginstance->gi_probes[0] = RID();
+ }
+
+ if (p_gi_probe_instance_count > 1) {
+ ginstance->gi_probes[1] = p_gi_probe_instances[1];
+ } else {
+ ginstance->gi_probes[1] = RID();
+ }
+}
+
RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) :
RendererSceneRenderRD(p_storage) {
singleton = this;
@@ -2788,11 +3133,10 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
{
//lightmaps
- scene_state.max_lightmaps = storage->lightmap_array_get_size();
+ scene_state.max_lightmaps = low_end ? 2 : MAX_LIGHTMAPS;
defines += "\n#define MAX_LIGHTMAP_TEXTURES " + itos(scene_state.max_lightmaps) + "\n";
defines += "\n#define MAX_LIGHTMAPS " + itos(scene_state.max_lightmaps) + "\n";
- scene_state.lightmaps = memnew_arr(LightmapData, scene_state.max_lightmaps);
scene_state.lightmap_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapData) * scene_state.max_lightmaps);
}
{
@@ -3015,12 +3359,6 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
render_list.init();
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));
{
@@ -3068,6 +3406,8 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
sampler.compare_op = RD::COMPARE_OP_LESS;
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
+
+ render_list_thread_threshold = GLOBAL_GET("rendering/forward_renderer/threaded_render_minimum_instances");
}
RendererSceneRenderForward::~RendererSceneRenderForward() {
@@ -3095,11 +3435,8 @@ RendererSceneRenderForward::~RendererSceneRenderForward() {
{
RD::get_singleton()->free(scene_state.uniform_buffer);
- RD::get_singleton()->free(scene_state.instance_buffer);
RD::get_singleton()->free(scene_state.lightmap_buffer);
RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
- memdelete_arr(scene_state.instances);
- memdelete_arr(scene_state.lightmaps);
memdelete_arr(scene_state.lightmap_captures);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.h b/servers/rendering/renderer_rd/renderer_scene_render_forward.h
index 4b37f4a391..8a6f268c46 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_forward.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.h
@@ -31,6 +31,7 @@
#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_H
#define RENDERING_SERVER_SCENE_RENDER_FORWARD_H
+#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
@@ -46,7 +47,9 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
enum {
SDFGI_MAX_CASCADES = 8,
- MAX_GI_PROBES = 8
+ MAX_GI_PROBES = 8,
+ MAX_LIGHTMAPS = 8,
+ MAX_GI_PROBES_PER_INSTANCE = 2,
};
/* Scene Shader */
@@ -197,14 +200,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
return static_cast<RendererSceneRenderForward *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
- /* Push Constant */
-
- struct PushConstant {
- uint32_t index;
- uint32_t pad;
- float bake_uv2_offset[2];
- };
-
/* Framebuffer */
struct RenderBufferDataForward : public RenderBufferData {
@@ -266,7 +261,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
- RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes);
+ RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps);
struct LightmapData {
float normal_xform[12];
@@ -292,16 +287,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
INSTANCE_DATA_FLAG_SKELETON = 1 << 19,
};
- struct InstanceData {
- float transform[16];
- float normal_transform[16];
- uint32_t flags;
- uint32_t instance_uniforms_ofs; //instance_offset in instancing/skeleton buffer
- uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
- uint32_t mask;
- float lightmap_uv_scale[4];
- };
-
struct SceneState {
struct UBO {
float projection_matrix[16];
@@ -385,7 +370,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RID uniform_buffer;
- LightmapData *lightmaps;
+ LightmapData lightmaps[MAX_LIGHTMAPS];
+ RID lightmap_ids[MAX_LIGHTMAPS];
+ bool lightmap_has_sh[MAX_LIGHTMAPS];
+ uint32_t lightmaps_used = 0;
uint32_t max_lightmaps;
RID lightmap_buffer;
@@ -393,47 +381,231 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
- RID instance_buffer;
- InstanceData *instances;
- uint32_t max_instances;
+ RID giprobe_ids[MAX_GI_PROBES];
+ uint32_t giprobes_used = 0;
bool used_screen_texture = false;
bool used_normal_texture = false;
bool used_depth_texture = false;
bool used_sss = false;
- uint32_t current_shader_index = 0;
- uint32_t current_material_index = 0;
} scene_state;
- /* Render List */
+ static RendererSceneRenderForward *singleton;
+ uint64_t render_pass;
+ double time;
+ RID default_shader;
+ RID default_material;
+ RID overdraw_material_shader;
+ RID overdraw_material;
+ RID wireframe_material_shader;
+ RID wireframe_material;
+ RID default_shader_rd;
+ RID default_shader_sdfgi_rd;
- struct RenderList {
- int max_elements;
+ RID default_vec4_xform_buffer;
+ RID default_vec4_xform_uniform_set;
- struct Element {
- RendererSceneRender::InstanceBase *instance;
- MaterialData *material;
- union {
- struct {
- //from least significant to most significant in sort, TODO: should be endian swapped on big endian
- uint64_t geometry_index : 20;
- uint64_t material_index : 15;
- uint64_t shader_index : 12;
- uint64_t uses_instancing : 1;
- uint64_t uses_forward_gi : 1;
- uint64_t uses_lightmap : 1;
- uint64_t depth_layer : 4;
- uint64_t priority : 8;
- };
-
- uint64_t sort_key;
+ enum PassMode {
+ PASS_MODE_COLOR,
+ PASS_MODE_COLOR_SPECULAR,
+ PASS_MODE_COLOR_TRANSPARENT,
+ PASS_MODE_SHADOW,
+ PASS_MODE_SHADOW_DP,
+ PASS_MODE_DEPTH,
+ PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
+ PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
+ PASS_MODE_DEPTH_MATERIAL,
+ PASS_MODE_SDF,
+ };
+
+ void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
+ void _setup_giprobes(const PagedArray<RID> &p_giprobes);
+ void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform);
+
+ struct GeometryInstanceSurfaceDataCache;
+
+ struct RenderListParameters {
+ GeometryInstanceSurfaceDataCache **elements = nullptr;
+ int element_count = 0;
+ bool reverse_cull = false;
+ PassMode pass_mode = PASS_MODE_COLOR;
+ bool no_gi = false;
+ RID render_pass_uniform_set;
+ bool force_wireframe = false;
+ Vector2 uv_offset;
+ Plane lod_plane;
+ float lod_distance_multiplier = 0.0;
+ float screen_lod_threshold = 0.0;
+ RD::FramebufferFormatID framebuffer_format = 0;
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) {
+ elements = p_elements;
+ element_count = p_element_count;
+ reverse_cull = p_reverse_cull;
+ pass_mode = p_pass_mode;
+ no_gi = p_no_gi;
+ render_pass_uniform_set = p_render_pass_uniform_set;
+ force_wireframe = p_force_wireframe;
+ uv_offset = p_uv_offset;
+ lod_plane = p_lod_plane;
+ lod_distance_multiplier = p_lod_distance_multiplier;
+ screen_lod_threshold = p_screen_lod_threshold;
+ }
+ };
+
+ template <PassMode p_pass_mode>
+ _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
+
+ void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
+
+ LocalVector<RD::DrawListID> thread_draw_lists;
+ void _render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params);
+ void _render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>());
+
+ uint32_t render_list_thread_threshold = 500;
+
+ void _fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false, bool p_using_opaque_gi = false);
+
+ Map<Size2i, RID> sdfgi_framebuffer_size_cache;
+
+ struct GeometryInstanceData;
+ struct GeometryInstanceForward;
+
+ struct GeometryInstanceLightmapSH {
+ Color sh[9];
+ };
+
+ // Cached data for drawing surfaces
+ struct GeometryInstanceSurfaceDataCache {
+ enum {
+ FLAG_PASS_DEPTH = 1,
+ FLAG_PASS_OPAQUE = 2,
+ FLAG_PASS_ALPHA = 4,
+ FLAG_PASS_SHADOW = 8,
+ FLAG_USES_SHARED_SHADOW_MATERIAL = 128,
+ FLAG_USES_SUBSURFACE_SCATTERING = 2048,
+ FLAG_USES_SCREEN_TEXTURE = 4096,
+ FLAG_USES_DEPTH_TEXTURE = 8192,
+ FLAG_USES_NORMAL_TEXTURE = 16384,
+ FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768,
+ };
+
+ union {
+ struct {
+ uint32_t geometry_id;
+ uint32_t material_id;
+ uint32_t shader_id;
+ uint32_t surface_type : 4;
+ uint32_t uses_forward_gi : 1; //set during addition
+ uint32_t uses_lightmap : 1; //set during addition
+ uint32_t depth_layer : 4; //set during addition
+ uint32_t priority : 8;
+ };
+ struct {
+ uint64_t sort_key1;
+ uint64_t sort_key2;
};
- uint32_t surface_index;
+ } sort;
+
+ RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
+ uint32_t flags = 0;
+ uint32_t surface_index = 0;
+
+ void *surface = nullptr;
+ RID material_uniform_set;
+ ShaderData *shader = nullptr;
+
+ void *surface_shadow = nullptr;
+ RID material_uniform_set_shadow;
+ ShaderData *shader_shadow = nullptr;
+
+ GeometryInstanceSurfaceDataCache *next = nullptr;
+ GeometryInstanceForward *owner = nullptr;
+ };
+
+ struct GeometryInstanceForward : public GeometryInstance {
+ //used during rendering
+ bool mirror = false;
+ bool non_uniform_scale = false;
+ float lod_bias = 0.0;
+ float lod_model_scale = 1.0;
+ AABB transformed_aabb; //needed for LOD
+ float depth = 0;
+ struct PushConstant {
+ float transform[16];
+ uint32_t flags;
+ uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables
+ uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index)
+ uint32_t layer_mask;
+ float lightmap_uv_scale[4];
+ } push_constant;
+ RID transforms_uniform_set;
+ uint32_t instance_count = 0;
+ RID mesh_instance;
+ bool can_sdfgi = false;
+ //used during setup
+ uint32_t base_flags = 0;
+ RID gi_probes[MAX_GI_PROBES_PER_INSTANCE];
+ RID lightmap_instance;
+ GeometryInstanceLightmapSH *lightmap_sh = nullptr;
+ GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
+ SelfList<GeometryInstanceForward> dirty_list_element;
+
+ struct Data {
+ //data used less often goes into regular heap
+ RID base;
+ RS::InstanceType base_type;
+
+ RID skeleton;
+
+ uint32_t layer_mask = 1;
+
+ Vector<RID> surface_materials;
+ RID material_override;
+ Transform transform;
+ AABB aabb;
+ int32_t shader_parameters_offset = -1;
+
+ bool use_dynamic_gi = false;
+ bool use_baked_light = false;
+ bool cast_double_sided_shaodows = false;
+ bool mirror = false;
+ Rect2 lightmap_uv_scale;
+ uint32_t lightmap_slice_index = 0;
+ bool dirty_dependencies = false;
+
+ RendererStorage::DependencyTracker dependency_tracker;
};
- Element *base_elements;
- Element **elements;
+ Data *data = nullptr;
+
+ GeometryInstanceForward() :
+ dirty_list_element(this) {}
+ };
+
+ static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
+
+ SelfList<GeometryInstanceForward>::List geometry_instance_dirty_list;
+
+ PagedAllocator<GeometryInstanceForward> geometry_instance_alloc;
+ PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
+ PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
+
+ void _geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
+ void _geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
+ void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _update_dirty_geometry_instances();
+
+ bool low_end = false;
+
+ /* Render List */
+
+ struct RenderList {
+ int max_elements;
+
+ GeometryInstanceSurfaceDataCache **elements = nullptr;
int element_count;
int alpha_element_count;
@@ -446,13 +618,13 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
//should eventually be replaced by radix
struct SortByKey {
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- return A->sort_key < B->sort_key;
+ _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
+ return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2);
}
};
void sort_by_key(bool p_alpha) {
- SortArray<Element *, SortByKey> sorter;
+ SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
@@ -461,14 +633,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}
struct SortByDepth {
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- return A->instance->depth < B->instance->depth;
+ _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
+ return (A->owner->depth < B->owner->depth);
}
};
void sort_by_depth(bool p_alpha) { //used for shadows
- SortArray<Element *, SortByDepth> sorter;
+ SortArray<GeometryInstanceSurfaceDataCache *, SortByDepth> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
@@ -477,20 +649,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}
struct SortByReverseDepthAndPriority {
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- uint32_t layer_A = uint32_t(A->priority);
- uint32_t layer_B = uint32_t(B->priority);
- if (layer_A == layer_B) {
- return A->instance->depth > B->instance->depth;
- } else {
- return layer_A < layer_B;
- }
+ _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
+ return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority);
}
};
void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
- SortArray<Element *, SortByReverseDepthAndPriority> sorter;
+ SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
@@ -498,32 +664,27 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}
}
- _FORCE_INLINE_ Element *add_element() {
+ _FORCE_INLINE_ void add_element(GeometryInstanceSurfaceDataCache *p_element) {
if (element_count + alpha_element_count >= max_elements) {
- return nullptr;
+ return;
}
- elements[element_count] = &base_elements[element_count];
- return elements[element_count++];
+ elements[element_count] = p_element;
+ element_count++;
}
- _FORCE_INLINE_ Element *add_alpha_element() {
+ _FORCE_INLINE_ void add_alpha_element(GeometryInstanceSurfaceDataCache *p_element) {
if (element_count + alpha_element_count >= max_elements) {
- return nullptr;
+ return;
}
int idx = max_elements - alpha_element_count - 1;
- elements[idx] = &base_elements[idx];
+ elements[idx] = p_element;
alpha_element_count++;
- return elements[idx];
}
void init() {
element_count = 0;
alpha_element_count = 0;
- elements = memnew_arr(Element *, max_elements);
- base_elements = memnew_arr(Element, max_elements);
- for (int i = 0; i < max_elements; i++) {
- elements[i] = &base_elements[i]; // assign elements
- }
+ elements = memnew_arr(GeometryInstanceSurfaceDataCache *, max_elements);
}
RenderList() {
@@ -532,63 +693,46 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
~RenderList() {
memdelete_arr(elements);
- memdelete_arr(base_elements);
}
};
RenderList render_list;
- static RendererSceneRenderForward *singleton;
- uint64_t render_pass;
- double time;
- RID default_shader;
- RID default_material;
- RID overdraw_material_shader;
- RID overdraw_material;
- RID wireframe_material_shader;
- RID wireframe_material;
- RID default_shader_rd;
- RID default_shader_sdfgi_rd;
-
- RID default_vec4_xform_buffer;
- RID default_vec4_xform_uniform_set;
-
- enum PassMode {
- PASS_MODE_COLOR,
- PASS_MODE_COLOR_SPECULAR,
- PASS_MODE_COLOR_TRANSPARENT,
- PASS_MODE_SHADOW,
- PASS_MODE_SHADOW_DP,
- PASS_MODE_DEPTH,
- PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
- PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
- PASS_MODE_DEPTH_MATERIAL,
- PASS_MODE_SDF,
- };
-
- void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
- void _setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform);
-
- void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
- 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, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
- _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
- _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
-
- void _fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false);
-
- Map<Size2i, RID> sdfgi_framebuffer_size_cache;
-
- bool low_end = false;
-
protected:
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
- virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, 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, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances);
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
+ virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, 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, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
+ virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
public:
+ virtual GeometryInstance *geometry_instance_create(RID p_base);
+ virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton);
+ virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
+ virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
+ virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
+ virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
+ virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
+ virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
+ virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable);
+ virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index);
+ virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9);
+ virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
+ virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
+
+ virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance);
+ virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
+
+ virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
+
+ virtual uint32_t geometry_instance_get_pair_mask();
+ virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
+ virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
+ virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
+ virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count);
+
virtual void set_time(double p_time, double p_step);
virtual bool free(RID p_rid);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 1edabed287..dad08179e7 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -4035,6 +4035,19 @@ void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Tran
/////////////////////////////////
+RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) {
+ LightmapInstance li;
+ li.lightmap = p_lightmap;
+ return lightmap_instance_owner.make_rid(li);
+}
+void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) {
+ LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap);
+ ERR_FAIL_COND(!li);
+ li->transform = p_transform;
+}
+
+/////////////////////////////////
+
RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) {
GIProbeInstance gi_probe;
gi_probe.probe = p_base;
@@ -4061,7 +4074,7 @@ bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {
return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
}
-void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<InstanceBase *> &p_dynamic_objects) {
+void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
@@ -4578,13 +4591,10 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
//this could probably be better parallelized in compute..
for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
- InstanceBase *instance = p_dynamic_objects[i];
- //not used, so clear
- instance->depth_layer = 0;
- instance->depth = 0;
+ GeometryInstance *instance = p_dynamic_objects[i];
//transform aabb to giprobe
- AABB aabb = (to_probe_xform * instance->transform).xform(instance->aabb);
+ AABB aabb = (to_probe_xform * geometry_instance_get_transform(instance)).xform(geometry_instance_get_aabb(instance));
//this needs to wrap to grid resolution to avoid jitter
//also extend margin a bit just in case
@@ -7101,7 +7111,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::get_singleton()->compute_list_end();
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
Color clear_color;
if (p_render_buffers.is_valid()) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -7177,7 +7187,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
}
}
-void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
LightInstance *light_instance = light_instance_owner.getornull(p_light);
ERR_FAIL_COND(!light_instance);
@@ -7353,11 +7363,11 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
}
}
-void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);
}
-void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) {
//print_line("rendering region " + itos(p_region));
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -7694,7 +7704,7 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, con
}
}
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
CameraMatrix cm;
@@ -7844,6 +7854,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
reflection_probe_instance_owner.free(p_rid);
} else if (decal_instance_owner.owns(p_rid)) {
decal_instance_owner.free(p_rid);
+ } else if (lightmap_instance_owner.owns(p_rid)) {
+ lightmap_instance_owner.free(p_rid);
} else if (gi_probe_instance_owner.owns(p_rid)) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
if (gi_probe->texture.is_valid()) {
@@ -7979,23 +7991,28 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
//RID sampled_light;
- InstanceBase ins;
+ GeometryInstance *gi = geometry_instance_create(p_base);
+
+ uint32_t sc = RSG::storage->mesh_get_surface_count(p_base);
+ Vector<RID> materials;
+ materials.resize(sc);
- ins.base_type = RSG::storage->get_base_type(p_base);
- ins.base = p_base;
- ins.materials.resize(RSG::storage->mesh_get_surface_count(p_base));
- for (int i = 0; i < ins.materials.size(); i++) {
- if (i < p_material_overrides.size()) {
- ins.materials.write[i] = p_material_overrides[i];
+ for (uint32_t i = 0; i < sc; i++) {
+ if (i < (uint32_t)p_material_overrides.size()) {
+ materials.write[i] = p_material_overrides[i];
}
}
+ geometry_instance_set_surface_materials(gi, materials);
+
if (cull_argument.size() == 0) {
cull_argument.push_back(nullptr);
}
- cull_argument[0] = &ins;
+ cull_argument[0] = gi;
_render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
+ geometry_instance_free(gi);
+
TypedArray<Image> ret;
{
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index af35e1b3b4..f81a35f025 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -109,12 +109,12 @@ protected:
void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);
void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used);
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
- virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, 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, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) = 0;
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
+ virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, 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, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
+ virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
@@ -137,8 +137,8 @@ protected:
void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);
// needed for a single argument calls (material and uv2)
- PagedArrayPool<InstanceBase *> cull_argument_pool;
- PagedArray<InstanceBase *> cull_argument; //need this to exist
+ PagedArrayPool<GeometryInstance *> cull_argument_pool;
+ PagedArray<GeometryInstance *> cull_argument; //need this to exist
private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
double time_step = 0;
@@ -374,6 +374,15 @@ private:
mutable RID_Owner<DecalInstance> decal_instance_owner;
+ /* LIGHTMAP INSTANCE */
+
+ struct LightmapInstance {
+ RID lightmap;
+ Transform transform;
+ };
+
+ mutable RID_Owner<LightmapInstance> lightmap_instance_owner;
+
/* GIPROBE INSTANCE */
struct GIProbeLight {
@@ -1473,6 +1482,9 @@ private:
bool low_end = false;
public:
+ virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
+ virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0;
+
/* SHADOW ATLAS API */
RID shadow_atlas_create();
@@ -1822,10 +1834,25 @@ public:
return decal->transform;
}
+ virtual RID lightmap_instance_create(RID p_lightmap);
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform);
+ _FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
+ return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr;
+ }
+
+ _FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) {
+ LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
+ return li->lightmap;
+ }
+ _FORCE_INLINE_ Transform lightmap_instance_get_transform(RID p_lightmap_instance) {
+ LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
+ return li->transform;
+ }
+
RID gi_probe_instance_create(RID p_base);
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
bool gi_probe_needs_update(RID p_probe) const;
- void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects);
+ void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);
void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
@@ -1900,16 +1927,16 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
+ void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
- void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
+ void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
- void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances);
+ void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances);
void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);
- void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances);
+ void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances);
virtual void set_scene_pass(uint64_t p_pass) {
scene_pass = p_pass;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 68983da408..bf7237cad0 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -1438,7 +1438,7 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
- material->instance_dependency.instance_notify_changed(false, true);
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
}
@@ -1547,7 +1547,8 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
}
if (p_shader.is_null()) {
- material->instance_dependency.instance_notify_changed(false, true);
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
+ material->shader_id = 0;
return;
}
@@ -1555,6 +1556,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
ERR_FAIL_COND(!shader);
material->shader = shader;
material->shader_type = shader->type;
+ material->shader_id = p_shader.get_local_index();
shader->owners.insert(material);
if (shader->type == SHADER_TYPE_MAX) {
@@ -1568,7 +1570,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
material->data->set_next_pass(material->next_pass);
material->data->set_render_priority(material->priority);
//updating happens later
- material->instance_dependency.instance_notify_changed(false, true);
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
@@ -1613,7 +1615,7 @@ void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_materi
material->data->set_next_pass(p_next_material);
}
- material->instance_dependency.instance_notify_changed(false, true);
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
}
void RendererStorageRD::material_set_render_priority(RID p_material, int priority) {
@@ -1663,10 +1665,10 @@ void RendererStorageRD::material_get_instance_shader_parameters(RID p_material,
}
}
-void RendererStorageRD::material_update_dependency(RID p_material, InstanceBaseDependency *p_instance) {
+void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
Material *material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material);
- p_instance->update_dependency(&material->instance_dependency);
+ p_instance->update_dependency(&material->dependency);
if (material->next_pass.is_valid()) {
material_update_dependency(material->next_pass, p_instance);
}
@@ -2596,7 +2598,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
_mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
}
- mesh->instance_dependency.instance_notify_changed(true, true);
+ mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
mesh->material_cache.clear();
}
@@ -2638,7 +2640,7 @@ void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
mesh->surfaces[p_surface]->material = p_material;
- mesh->instance_dependency.instance_notify_changed(false, true);
+ mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
mesh->material_cache.clear();
}
@@ -2858,8 +2860,8 @@ void RendererStorageRD::mesh_clear(RID p_mesh) {
MeshInstance *mi = E->get();
_mesh_instance_clear(mi);
}
- mesh->instance_dependency.instance_notify_changed(true, true);
mesh->has_bone_weights = false;
+ mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
}
bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
@@ -3298,6 +3300,8 @@ void RendererStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS:
if (multimesh->instances) {
multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
}
+
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH);
}
int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const {
@@ -3331,7 +3335,7 @@ void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
}
}
- multimesh->instance_dependency.instance_notify_changed(true, true);
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
}
#define MULTIMESH_DIRTY_REGION_SIZE 512
@@ -3690,7 +3694,7 @@ void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float
const float *data = p_buffer.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- multimesh->instance_dependency.instance_notify_changed(true, false);
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
}
@@ -3731,6 +3735,8 @@ void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_v
}
multimesh->visible_instances = p_visible;
+
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
}
int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
@@ -3788,7 +3794,7 @@ void RendererStorageRD::_update_dirty_multimeshes() {
//aabb is dirty..
_multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->aabb_dirty = false;
- multimesh->instance_dependency.instance_notify_changed(true, false);
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
}
@@ -3926,7 +3932,7 @@ void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
particles->custom_aabb = p_aabb;
- particles->instance_dependency.instance_notify_changed(true, false);
+ particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) {
@@ -4155,24 +4161,18 @@ RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass)
return particles->draw_passes[p_pass];
}
-void RendererStorageRD::particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance) {
- RendererSceneRender::InstanceBase *instance = static_cast<RendererSceneRender::InstanceBase *>(p_instance);
-
+void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
- ERR_FAIL_COND(instance->base_type != RS::INSTANCE_PARTICLES_COLLISION);
-
- particles->collisions.insert(instance);
+ particles->collisions.insert(p_particles_collision_instance);
}
-void RendererStorageRD::particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance) {
- RendererSceneRender::InstanceBase *instance = static_cast<RendererSceneRender::InstanceBase *>(p_instance);
-
+void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
- particles->collisions.erase(instance);
+ particles->collisions.erase(p_particles_collision_instance);
}
void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) {
@@ -4272,9 +4272,15 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
to_particles = p_particles->emission_transform.affine_inverse();
}
uint32_t collision_3d_textures_used = 0;
- for (const Set<RendererSceneRender::InstanceBase *>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
- ParticlesCollision *pc = particles_collision_owner.getornull(E->get()->base);
- Transform to_collider = E->get()->transform;
+ for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(E->get());
+ if (!pci || !pci->active) {
+ continue;
+ }
+ ParticlesCollision *pc = particles_collision_owner.getornull(pci->collision);
+ ERR_CONTINUE(!pc);
+
+ Transform to_collider = pci->transform;
if (p_particles->use_local_coords) {
to_collider = to_particles * to_collider;
}
@@ -4687,7 +4693,7 @@ void RendererStorageRD::update_particles() {
RD::get_singleton()->compute_list_end();
}
- particles->instance_dependency.instance_notify_changed(true, false); //make sure shadows are updated
+ particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
}
@@ -4986,7 +4992,7 @@ void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_c
particles_collision->heightfield_texture = RID();
}
particles_collision->type = p_type;
- particles_collision->instance_dependency.instance_notify_changed(true, false);
+ particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
@@ -5000,7 +5006,7 @@ void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_co
ERR_FAIL_COND(!particles_collision);
particles_collision->radius = p_radius;
- particles_collision->instance_dependency.instance_notify_changed(true, false);
+ particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
@@ -5008,7 +5014,7 @@ void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_coll
ERR_FAIL_COND(!particles_collision);
particles_collision->extents = p_extents;
- particles_collision->instance_dependency.instance_notify_changed(true, false);
+ particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) {
@@ -5042,7 +5048,7 @@ void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_co
void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
- particles_collision->instance_dependency.instance_notify_changed(true, false);
+ particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
@@ -5096,6 +5102,22 @@ bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_colli
return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
}
+RID RendererStorageRD::particles_collision_instance_create(RID p_collision) {
+ ParticlesCollisionInstance pci;
+ pci.collision = p_collision;
+ return particles_collision_instance_owner.make_rid(pci);
+}
+void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->transform = p_transform;
+}
+void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->active = p_active;
+}
+
/* SKELETON API */
RID RendererStorageRD::skeleton_create() {
@@ -5149,6 +5171,8 @@ void RendererStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d
skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
}
}
+
+ skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_DATA);
}
int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
@@ -5269,7 +5293,8 @@ void RendererStorageRD::_update_dirty_skeletons() {
skeleton_dirty_list = skeleton->dirty_list;
- skeleton->instance_dependency.instance_notify_changed(true, false);
+ skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES);
+
skeleton->version++;
skeleton->dirty = false;
@@ -5290,17 +5315,20 @@ RID RendererStorageRD::light_create(RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
+ light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0;
light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
+ light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
- light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+ light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
- light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 1.0;
+ light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
return light_owner.make_rid(light);
}
@@ -5328,7 +5356,7 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo
case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
case RS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} break;
default: {
}
@@ -5343,7 +5371,7 @@ void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
light->shadow = p_enabled;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
@@ -5385,7 +5413,7 @@ void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
light->cull_mask = p_mask;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
@@ -5395,7 +5423,7 @@ void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_ena
light->reverse_cull = p_enabled;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
@@ -5405,7 +5433,7 @@ void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bak
light->bake_mode = p_bake_mode;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
@@ -5415,7 +5443,7 @@ void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_casc
light->max_sdfgi_cascade = p_cascade;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
@@ -5425,7 +5453,7 @@ void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniSha
light->omni_shadow_mode = p_mode;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) {
@@ -5441,7 +5469,7 @@ void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::Light
light->directional_shadow_mode = p_mode;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
@@ -5450,7 +5478,7 @@ void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_e
light->directional_blend_splits = p_enable;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const {
@@ -5549,7 +5577,7 @@ void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::Reflec
ERR_FAIL_COND(!reflection_probe);
reflection_probe->update_mode = p_mode;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
@@ -5586,7 +5614,7 @@ void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_d
reflection_probe->max_distance = p_distance;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
@@ -5597,7 +5625,7 @@ void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3
return;
}
reflection_probe->extents = p_extents;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
@@ -5605,7 +5633,7 @@ void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Ve
ERR_FAIL_COND(!reflection_probe);
reflection_probe->origin_offset = p_offset;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
@@ -5613,7 +5641,7 @@ void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_ena
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
@@ -5628,7 +5656,7 @@ void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_
ERR_FAIL_COND(!reflection_probe);
reflection_probe->enable_shadows = p_enable;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
@@ -5636,7 +5664,7 @@ void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_l
ERR_FAIL_COND(!reflection_probe);
reflection_probe->cull_mask = p_layers;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
@@ -5653,7 +5681,7 @@ void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_
reflection_probe->lod_threshold = p_ratio;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const {
@@ -5771,7 +5799,7 @@ void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents)
Decal *decal = decal_owner.getornull(p_decal);
ERR_FAIL_COND(!decal);
decal->extents = p_extents;
- decal->instance_dependency.instance_notify_changed(true, false);
+ decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
@@ -5795,7 +5823,7 @@ void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type,
texture_add_to_decal_atlas(decal->textures[p_type]);
}
- decal->instance_dependency.instance_notify_changed(false, true);
+ decal->dependency.changed_notify(DEPENDENCY_CHANGED_DECAL);
}
void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) {
@@ -5820,7 +5848,7 @@ void RendererStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
Decal *decal = decal_owner.getornull(p_decal);
ERR_FAIL_COND(!decal);
decal->cull_mask = p_layers;
- decal->instance_dependency.instance_notify_changed(true, false);
+ decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
@@ -5977,7 +6005,7 @@ void RendererStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_
gi_probe->version++;
gi_probe->data_version++;
- gi_probe->instance_dependency.instance_notify_changed(true, false);
+ gi_probe->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
AABB RendererStorageRD::gi_probe_get_bounds(RID p_gi_probe) const {
@@ -7055,45 +7083,45 @@ void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_ta
rt->backbuffer_uniform_set = p_uniform_set;
}
-void RendererStorageRD::base_update_dependency(RID p_base, InstanceBaseDependency *p_instance) {
+void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
if (mesh_owner.owns(p_base)) {
Mesh *mesh = mesh_owner.getornull(p_base);
- p_instance->update_dependency(&mesh->instance_dependency);
+ p_instance->update_dependency(&mesh->dependency);
} else if (multimesh_owner.owns(p_base)) {
MultiMesh *multimesh = multimesh_owner.getornull(p_base);
- p_instance->update_dependency(&multimesh->instance_dependency);
+ p_instance->update_dependency(&multimesh->dependency);
if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance);
}
} else if (reflection_probe_owner.owns(p_base)) {
ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
- p_instance->update_dependency(&rp->instance_dependency);
+ p_instance->update_dependency(&rp->dependency);
} else if (decal_owner.owns(p_base)) {
Decal *decal = decal_owner.getornull(p_base);
- p_instance->update_dependency(&decal->instance_dependency);
+ p_instance->update_dependency(&decal->dependency);
} else if (gi_probe_owner.owns(p_base)) {
GIProbe *gip = gi_probe_owner.getornull(p_base);
- p_instance->update_dependency(&gip->instance_dependency);
+ p_instance->update_dependency(&gip->dependency);
} else if (lightmap_owner.owns(p_base)) {
Lightmap *lm = lightmap_owner.getornull(p_base);
- p_instance->update_dependency(&lm->instance_dependency);
+ p_instance->update_dependency(&lm->dependency);
} else if (light_owner.owns(p_base)) {
Light *l = light_owner.getornull(p_base);
- p_instance->update_dependency(&l->instance_dependency);
+ p_instance->update_dependency(&l->dependency);
} else if (particles_owner.owns(p_base)) {
Particles *p = particles_owner.getornull(p_base);
- p_instance->update_dependency(&p->instance_dependency);
+ p_instance->update_dependency(&p->dependency);
} else if (particles_collision_owner.owns(p_base)) {
ParticlesCollision *pc = particles_collision_owner.getornull(p_base);
- p_instance->update_dependency(&pc->instance_dependency);
+ p_instance->update_dependency(&pc->dependency);
}
}
-void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, InstanceBaseDependency *p_instance) {
+void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton);
- p_instance->update_dependency(&skeleton->instance_dependency);
+ p_instance->update_dependency(&skeleton->dependency);
}
RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
@@ -8114,12 +8142,13 @@ bool RendererStorageRD::free(RID p_rid) {
_update_queued_materials();
}
material_set_shader(p_rid, RID()); //clean up shader
- material->instance_dependency.instance_notify_deleted(p_rid);
+ material->dependency.deleted_notify(p_rid);
+
material_owner.free(p_rid);
} else if (mesh_owner.owns(p_rid)) {
mesh_clear(p_rid);
Mesh *mesh = mesh_owner.getornull(p_rid);
- mesh->instance_dependency.instance_notify_deleted(p_rid);
+ mesh->dependency.deleted_notify(p_rid);
if (mesh->instances.size()) {
ERR_PRINT("deleting mesh with active instances");
}
@@ -8136,17 +8165,17 @@ bool RendererStorageRD::free(RID p_rid) {
_update_dirty_multimeshes();
multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
- multimesh->instance_dependency.instance_notify_deleted(p_rid);
+ multimesh->dependency.deleted_notify(p_rid);
multimesh_owner.free(p_rid);
} else if (skeleton_owner.owns(p_rid)) {
_update_dirty_skeletons();
skeleton_allocate(p_rid, 0);
Skeleton *skeleton = skeleton_owner.getornull(p_rid);
- skeleton->instance_dependency.instance_notify_deleted(p_rid);
+ skeleton->dependency.deleted_notify(p_rid);
skeleton_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->dependency.deleted_notify(p_rid);
reflection_probe_owner.free(p_rid);
} else if (decal_owner.owns(p_rid)) {
Decal *decal = decal_owner.getornull(p_rid);
@@ -8155,30 +8184,30 @@ bool RendererStorageRD::free(RID p_rid) {
texture_remove_from_decal_atlas(decal->textures[i]);
}
}
- decal->instance_dependency.instance_notify_deleted(p_rid);
+ decal->dependency.deleted_notify(p_rid);
decal_owner.free(p_rid);
} else if (gi_probe_owner.owns(p_rid)) {
gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
- gi_probe->instance_dependency.instance_notify_deleted(p_rid);
+ gi_probe->dependency.deleted_notify(p_rid);
gi_probe_owner.free(p_rid);
} else if (lightmap_owner.owns(p_rid)) {
lightmap_set_textures(p_rid, RID(), false);
Lightmap *lightmap = lightmap_owner.getornull(p_rid);
- lightmap->instance_dependency.instance_notify_deleted(p_rid);
+ lightmap->dependency.deleted_notify(p_rid);
lightmap_owner.free(p_rid);
} else if (light_owner.owns(p_rid)) {
light_set_projector(p_rid, RID()); //clear projector
// delete the texture
Light *light = light_owner.getornull(p_rid);
- light->instance_dependency.instance_notify_deleted(p_rid);
+ light->dependency.deleted_notify(p_rid);
light_owner.free(p_rid);
} else if (particles_owner.owns(p_rid)) {
Particles *particles = particles_owner.getornull(p_rid);
_particles_free_data(particles);
- particles->instance_dependency.instance_notify_deleted(p_rid);
+ particles->dependency.deleted_notify(p_rid);
particles_owner.free(p_rid);
} else if (particles_collision_owner.owns(p_rid)) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_rid);
@@ -8186,8 +8215,10 @@ bool RendererStorageRD::free(RID p_rid) {
if (particles_collision->heightfield_texture.is_valid()) {
RD::get_singleton()->free(particles_collision->heightfield_texture);
}
- particles_collision->instance_dependency.instance_notify_deleted(p_rid);
+ particles_collision->dependency.deleted_notify(p_rid);
particles_collision_owner.free(p_rid);
+ } else if (particles_collision_instance_owner.owns(p_rid)) {
+ particles_collision_instance_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
RenderTarget *rt = render_target_owner.getornull(p_rid);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 6d1587185e..bd27936e38 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -360,6 +360,7 @@ private:
Shader *shader;
//shortcut to shader data and type
ShaderType shader_type;
+ uint32_t shader_id = 0;
bool update_requested;
bool uniform_dirty;
bool texture_dirty;
@@ -367,7 +368,7 @@ private:
Map<StringName, Variant> params;
int32_t priority;
RID next_pass;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
@@ -460,7 +461,7 @@ private:
List<MeshInstance *> instances;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<Mesh> mesh_owner;
@@ -563,7 +564,7 @@ private:
bool dirty = false;
MultiMesh *dirty_list = nullptr;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<MultiMesh> multimesh_owner;
@@ -734,7 +735,7 @@ private:
ParticleEmissionBuffer *emission_buffer = nullptr;
RID emission_storage_buffer;
- Set<RendererSceneRender::InstanceBase *> collisions;
+ Set<RID> collisions;
Particles() :
inactive(true),
@@ -761,7 +762,7 @@ private:
clear(true) {
}
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
ParticlesFrameParams frame_params;
};
@@ -889,11 +890,19 @@ private:
RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<ParticlesCollision> particles_collision_owner;
+ struct ParticlesCollisionInstance {
+ RID collision;
+ Transform transform;
+ bool active = false;
+ };
+
+ mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+
/* Skeleton */
struct Skeleton {
@@ -911,7 +920,7 @@ private:
uint64_t version = 1;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<Skeleton> skeleton_owner;
@@ -943,7 +952,7 @@ private:
bool directional_sky_only = false;
uint64_t version = 0;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<Light> light_owner;
@@ -966,7 +975,7 @@ private:
uint32_t cull_mask = (1 << 20) - 1;
float lod_threshold = 0.01;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
@@ -987,7 +996,7 @@ private:
float distance_fade_length = 1;
float normal_fade = 0.0;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<Decal> decal_owner;
@@ -1025,7 +1034,7 @@ private:
uint32_t version = 1;
uint32_t data_version = 1;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
GiprobeSdfShaderRD giprobe_sdf_shader;
@@ -1054,7 +1063,7 @@ private:
int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
};
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
bool using_lightmap_array; //high end uses this
@@ -1347,11 +1356,16 @@ public:
void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
- void material_update_dependency(RID p_material, InstanceBaseDependency *p_instance);
+ void material_update_dependency(RID p_material, DependencyTracker *p_instance);
void material_force_update_textures(RID p_material, ShaderType p_shader_type);
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
+ _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
+ Material *material = material_owner.getornull(p_material);
+ return material->shader_id;
+ }
+
_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
Material *material = material_owner.getornull(p_material);
if (!material || material->shader_type != p_shader_type) {
@@ -1664,6 +1678,10 @@ public:
void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
+ _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
+ return skeleton_owner.getornull(p_skeleton) != nullptr;
+ }
+
_FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND_V(!skeleton, RID());
@@ -1827,8 +1845,8 @@ public:
Color reflection_probe_get_ambient_color(RID p_probe) const;
float reflection_probe_get_ambient_color_energy(RID p_probe) const;
- void base_update_dependency(RID p_base, InstanceBaseDependency *p_instance);
- void skeleton_update_dependency(RID p_skeleton, InstanceBaseDependency *p_instance);
+ void base_update_dependency(RID p_base, DependencyTracker *p_instance);
+ void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance);
/* DECAL API */
@@ -1977,7 +1995,11 @@ public:
_FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const {
return lightmap_probe_capture_update_speed;
}
-
+ _FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND_V(!lm, RID());
+ return lm->light_texture;
+ }
_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
@@ -2078,8 +2100,8 @@ public:
return particles->particles_transforms_buffer_uniform_set;
}
- virtual void particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance);
- virtual void particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance);
+ virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance);
+ virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance);
/* PARTICLES COLLISION */
@@ -2099,6 +2121,11 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
+ //used from 2D and 3D
+ virtual RID particles_collision_instance_create(RID p_collision);
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform);
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
+
/* GLOBAL VARIABLES API */
virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index d1f07a354f..e955cead05 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -360,7 +360,7 @@ void ShaderRD::_compile_version(Version *p_version) {
p_version->variants = memnew_arr(RID, variant_defines.size());
#if 1
- RendererCompositorRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
+ RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
#else
for (int i = 0; i < variant_defines.size(); i++) {
_compile_variant(i, p_version);
diff --git a/servers/rendering/renderer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/giprobe.glsl
index ea4237a45e..4f4753d147 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe.glsl
+++ b/servers/rendering/renderer_rd/shaders/giprobe.glsl
@@ -208,6 +208,15 @@ float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
return occlusion; //max(0.0,distance);
}
+float get_omni_attenuation(float distance, float inv_range, float decay) {
+ float nd = distance * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(distance, 0.0001), -decay);
+}
+
bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) {
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
@@ -220,7 +229,7 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
return false;
}
- attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
+ attenuation = get_omni_attenuation(distance, 1.0 / lights.data[light].radius, lights.data[light].attenuation);
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward.glsl b/servers/rendering/renderer_rd/shaders/scene_forward.glsl
index 1c12a8a4c7..0518976322 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward.glsl
@@ -97,8 +97,6 @@ VERTEX_SHADER_GLOBALS
invariant gl_Position;
-layout(location = 7) flat out uint instance_index;
-
#ifdef MODE_DUAL_PARABOLOID
layout(location = 8) out float dp_clip;
@@ -106,22 +104,27 @@ layout(location = 8) out float dp_clip;
#endif
void main() {
- instance_index = draw_call.instance_index;
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
#endif
- mat4 world_matrix = instances.data[instance_index].transform;
- mat3 world_normal_matrix = mat3(instances.data[instance_index].normal_transform);
+ mat4 world_matrix = draw_call.transform;
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) {
+ mat3 world_normal_matrix;
+ if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
+ world_normal_matrix = inverse(mat3(world_matrix));
+ } else {
+ world_normal_matrix = mat3(world_matrix);
+ }
+
+ if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH)) {
//multimesh, instances are for it
- uint offset = (instances.data[instance_index].flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;
+ uint offset = (draw_call.flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;
offset *= gl_InstanceIndex;
mat4 matrix;
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+ if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
offset += 2;
} else {
@@ -129,14 +132,14 @@ void main() {
offset += 3;
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+ if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
#ifdef COLOR_USED
color_interp *= transforms.data[offset];
#endif
offset += 1;
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+ if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
instance_custom = transforms.data[offset];
}
@@ -144,10 +147,6 @@ void main() {
matrix = transpose(matrix);
world_matrix = world_matrix * matrix;
world_normal_matrix = world_normal_matrix * mat3(matrix);
-
- } else {
- //not a multimesh, instances are for multiple draw calls
- instance_index += gl_InstanceIndex;
}
vec3 vertex = vertex_attrib;
@@ -162,7 +161,7 @@ void main() {
#endif
#if 0
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) {
+ if (bool(draw_call.flags & INSTANCE_FLAGS_SKELETON)) {
//multimesh, instances are for it
uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3;
@@ -305,7 +304,7 @@ VERTEX_SHADER_CODE
#endif
#ifdef MODE_RENDER_MATERIAL
if (scene_data.material_uv2_mode) {
- gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0;
+ gl_Position.xy = (uv2_attrib.xy + draw_call.lightmap_uv_scale.xy) * 2.0 - 1.0;
gl_Position.z = 0.00001;
gl_Position.w = 1.0;
}
@@ -345,8 +344,6 @@ 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;
@@ -355,8 +352,7 @@ layout(location = 8) in float dp_clip;
//defines to keep compatibility with vertex
-#define world_matrix instances.data[instance_index].transform
-#define world_normal_matrix instances.data[instance_index].normal_transform
+#define world_matrix draw_call.transform
#define projection_matrix scene_data.projection_matrix
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
@@ -895,6 +891,15 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
#endif //USE_NO_SHADOWS
+float get_omni_attenuation(float distance, float inv_range, float decay) {
+ float nd = distance * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(distance, 0.0001), -decay);
+}
+
void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
@@ -920,9 +925,8 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
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);
+ float omni_attenuation = get_omni_attenuation(light_length, lights.data[idx].inv_radius, attenuation_energy.x);
float light_attenuation = omni_attenuation;
vec3 shadow_attenuation = vec3(1.0);
vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
@@ -1209,9 +1213,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
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);
+ float spot_attenuation = get_omni_attenuation(light_length, lights.data[idx].inv_radius, 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);
@@ -1971,7 +1974,7 @@ FRAGMENT_SHADER_CODE
for (uint i = 0; i < decal_count; i++) {
uint decal_index = cluster_data.indices[decal_pointer + i];
- if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) {
+ if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) {
continue; //not masked
}
@@ -2102,8 +2105,8 @@ FRAGMENT_SHADER_CODE
#ifdef USE_LIGHTMAP
//lightmap
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
- uint index = instances.data[instance_index].gi_offset;
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
+ uint index = draw_call.gi_offset;
vec3 wnormal = mat3(scene_data.camera_matrix) * normal;
const float c1 = 0.429043;
@@ -2122,12 +2125,12 @@ FRAGMENT_SHADER_CODE
2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
- } else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
- bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
- uint ofs = instances.data[instance_index].gi_offset & 0xFFF;
+ } else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
+ bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
+ uint ofs = draw_call.gi_offset & 0xFFFF;
vec3 uvw;
- uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy;
- uvw.z = float((instances.data[instance_index].gi_offset >> 12) & 0xFF);
+ uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy;
+ uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF);
if (uses_sh) {
uvw.z *= 4.0; //SH textures use 4 times more data
@@ -2136,7 +2139,7 @@ FRAGMENT_SHADER_CODE
vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
- uint idx = instances.data[instance_index].gi_offset >> 20;
+ uint idx = draw_call.gi_offset >> 20;
vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
ambient_light += lm_light_l0 * 0.282095f;
@@ -2156,7 +2159,7 @@ FRAGMENT_SHADER_CODE
}
#elif defined(USE_FORWARD_GI)
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
//make vertex orientation the world one, but still align to camera
vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex;
@@ -2228,9 +2231,9 @@ FRAGMENT_SHADER_CODE
}
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
+ uint index1 = draw_call.gi_offset & 0xFFFF;
vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
//find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
@@ -2242,7 +2245,7 @@ FRAGMENT_SHADER_CODE
vec4 spec_accum = vec4(0.0);
gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- uint index2 = instances.data[instance_index].gi_offset >> 16;
+ uint index2 = draw_call.gi_offset >> 16;
if (index2 != 0xFFFF) {
gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
@@ -2261,7 +2264,7 @@ FRAGMENT_SHADER_CODE
}
#elif !defined(LOW_END_MODE)
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
ivec2 coord;
@@ -2343,7 +2346,7 @@ FRAGMENT_SHADER_CODE
{ //directional light
for (uint i = 0; i < scene_data.directional_light_count; i++) {
- if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) {
+ if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {
continue; //not masked
}
@@ -2613,7 +2616,7 @@ FRAGMENT_SHADER_CODE
for (uint i = 0; i < omni_light_count; i++) {
uint light_index = cluster_data.indices[omni_light_pointer + i];
- if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
+ if (!bool(lights.data[light_index].mask & draw_call.layer_mask)) {
continue; //not masked
}
@@ -2651,7 +2654,7 @@ FRAGMENT_SHADER_CODE
for (uint i = 0; i < spot_light_count; i++) {
uint light_index = cluster_data.indices[spot_light_pointer + i];
- if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
+ if (!bool(lights.data[light_index].mask & draw_call.layer_mask)) {
continue; //not masked
}
@@ -2822,9 +2825,9 @@ FRAGMENT_SHADER_CODE
normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
#ifdef MODE_RENDER_GIPROBE
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- uint index2 = instances.data[instance_index].gi_offset >> 16;
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
+ uint index1 = draw_call.gi_offset & 0xFFFF;
+ uint index2 = draw_call.gi_offset >> 16;
giprobe_buffer.x = index1 & 0xFF;
giprobe_buffer.y = index2 & 0xFF;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl
index 17ed22f58a..87ce74ba88 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl
@@ -12,9 +12,12 @@
#endif
layout(push_constant, binding = 0, std430) uniform DrawCall {
- uint instance_index;
- uint pad; //16 bits minimum size
- vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise
+ mat4 transform;
+ uint flags;
+ uint instance_uniforms_ofs; //base offset in global buffer for instance variables
+ uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
+ uint layer_mask;
+ vec4 lightmap_uv_scale;
}
draw_call;
@@ -134,21 +137,7 @@ scene_data;
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7
#define INSTANCE_FLAGS_SKELETON (1 << 19)
-
-struct InstanceData {
- mat4 transform;
- mat4 normal_transform;
- uint flags;
- uint instance_uniforms_ofs; //base offset in global buffer for instance variables
- uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
- uint layer_mask;
- vec4 lightmap_uv_scale;
-};
-
-layout(set = 0, binding = 4, std430) restrict readonly buffer Instances {
- InstanceData data[];
-}
-instances;
+#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 20)
layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
LightData data[];
@@ -177,35 +166,33 @@ layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps {
}
lightmaps;
-layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
-
struct LightmapCapture {
vec4 sh[9];
};
-layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures {
+layout(set = 0, binding = 11, std140) restrict readonly buffer LightmapCaptures {
LightmapCapture data[];
}
lightmap_captures;
-layout(set = 0, binding = 13) uniform texture2D decal_atlas;
-layout(set = 0, binding = 14) uniform texture2D decal_atlas_srgb;
+layout(set = 0, binding = 12) uniform texture2D decal_atlas;
+layout(set = 0, binding = 13) uniform texture2D decal_atlas_srgb;
-layout(set = 0, binding = 15, std430) restrict readonly buffer Decals {
+layout(set = 0, binding = 14, std430) restrict readonly buffer Decals {
DecalData data[];
}
decals;
-layout(set = 0, binding = 16) uniform utexture3D cluster_texture;
+layout(set = 0, binding = 15) uniform utexture3D cluster_texture;
-layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData {
+layout(set = 0, binding = 16, std430) restrict readonly buffer ClusterData {
uint indices[];
}
cluster_data;
-layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas;
+layout(set = 0, binding = 17) uniform texture2D directional_shadow_atlas;
-layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 18, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
@@ -219,7 +206,7 @@ struct SDFGIProbeCascadeData {
float to_cell; // 1/bounds * grid_size
};
-layout(set = 0, binding = 20, std140) uniform SDFGI {
+layout(set = 0, binding = 19, std140) uniform SDFGI {
vec3 grid_size;
uint max_cascades;
@@ -269,18 +256,20 @@ layout(set = 1, binding = 1) uniform textureCubeArray reflection_atlas;
layout(set = 1, binding = 2) uniform texture2D shadow_atlas;
+layout(set = 1, binding = 3) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+
#ifndef LOW_END_MODE
-layout(set = 1, binding = 3) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
+layout(set = 1, binding = 4) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
#endif
/* Set 3, Render Buffers */
#ifdef MODE_RENDER_SDF
-layout(r16ui, set = 1, binding = 4) uniform restrict writeonly uimage3D albedo_volume_grid;
-layout(r32ui, set = 1, binding = 5) uniform restrict writeonly uimage3D emission_grid;
-layout(r32ui, set = 1, binding = 6) uniform restrict writeonly uimage3D emission_aniso_grid;
-layout(r32ui, set = 1, binding = 7) uniform restrict uimage3D geom_facing_grid;
+layout(r16ui, set = 1, binding = 5) uniform restrict writeonly uimage3D albedo_volume_grid;
+layout(r32ui, set = 1, binding = 6) uniform restrict writeonly uimage3D emission_grid;
+layout(r32ui, set = 1, binding = 7) uniform restrict writeonly uimage3D emission_aniso_grid;
+layout(r32ui, set = 1, binding = 8) uniform restrict uimage3D geom_facing_grid;
//still need to be present for shaders that use it, so remap them to something
#define depth_buffer shadow_atlas
@@ -289,17 +278,17 @@ layout(r32ui, set = 1, binding = 7) uniform restrict uimage3D geom_facing_grid;
#else
-layout(set = 1, binding = 4) uniform texture2D depth_buffer;
-layout(set = 1, binding = 5) uniform texture2D color_buffer;
+layout(set = 1, binding = 5) uniform texture2D depth_buffer;
+layout(set = 1, binding = 6) uniform texture2D color_buffer;
#ifndef LOW_END_MODE
-layout(set = 1, binding = 6) uniform texture2D normal_roughness_buffer;
-layout(set = 1, binding = 7) uniform texture2D ao_buffer;
-layout(set = 1, binding = 8) uniform texture2D ambient_buffer;
-layout(set = 1, binding = 9) uniform texture2D reflection_buffer;
-layout(set = 1, binding = 10) uniform texture2DArray sdfgi_lightprobe_texture;
-layout(set = 1, binding = 11) uniform texture3D sdfgi_occlusion_cascades;
+layout(set = 1, binding = 7) uniform texture2D normal_roughness_buffer;
+layout(set = 1, binding = 8) uniform texture2D ao_buffer;
+layout(set = 1, binding = 9) uniform texture2D ambient_buffer;
+layout(set = 1, binding = 10) uniform texture2D reflection_buffer;
+layout(set = 1, binding = 11) uniform texture2DArray sdfgi_lightprobe_texture;
+layout(set = 1, binding = 12) uniform texture3D sdfgi_occlusion_cascades;
struct GIProbeData {
mat4 xform;
@@ -317,12 +306,12 @@ struct GIProbeData {
uint mipmaps;
};
-layout(set = 1, binding = 12, std140) uniform GIProbes {
+layout(set = 1, binding = 13, std140) uniform GIProbes {
GIProbeData data[MAX_GI_PROBES];
}
gi_probes;
-layout(set = 1, binding = 13) uniform texture3D volumetric_fog_texture;
+layout(set = 1, binding = 14) uniform texture3D volumetric_fog_texture;
#endif // LOW_END_MODE
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
index 61e4bf5e18..30dbf5871f 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
@@ -112,6 +112,15 @@ vec2 octahedron_encode(vec3 n) {
return n.xy;
}
+float get_omni_attenuation(float distance, float inv_range, float decay) {
+ float nd = distance * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(distance, 0.0001), -decay);
+}
+
void main() {
uint voxel_index = uint(gl_GlobalInvocationID.x);
@@ -184,14 +193,15 @@ void main() {
direction = normalize(rel_vec);
light_distance = length(rel_vec);
rel_vec.y /= params.y_mult;
- attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation);
+ attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation);
+
} break;
case LIGHT_TYPE_SPOT: {
vec3 rel_vec = lights.data[i].position - position;
direction = normalize(rel_vec);
light_distance = length(rel_vec);
rel_vec.y /= params.y_mult;
- attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation);
+ attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation);
float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction));
if (angle > lights.data[i].spot_angle) {
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
index 13b162f0c9..498a6ddb5b 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
@@ -169,6 +169,15 @@ vec3 hash3f(uvec3 x) {
return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF));
}
+float get_omni_attenuation(float distance, float inv_range, float decay) {
+ float nd = distance * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(distance, 0.0001), -decay);
+}
+
void main() {
vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
@@ -270,14 +279,14 @@ void main() {
uint light_index = cluster_data.indices[omni_light_pointer + i];
vec3 light_pos = lights.data[i].position;
- float d = distance(lights.data[i].position, view_pos) * lights.data[i].inv_radius;
+ float d = distance(lights.data[i].position, view_pos);
vec3 shadow_attenuation = vec3(1.0);
- if (d < 1.0) {
+ if (d * lights.data[i].inv_radius < 1.0) {
vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy);
vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular);
- float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x);
+ float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x);
vec3 light = attenuation_energy.y * color_specular.rgb / M_PI;
@@ -326,14 +335,14 @@ void main() {
vec3 light_pos = lights.data[i].position;
vec3 light_rel_vec = lights.data[i].position - view_pos;
- float d = length(light_rel_vec) * lights.data[i].inv_radius;
+ float d = length(light_rel_vec);
vec3 shadow_attenuation = vec3(1.0);
- if (d < 1.0) {
+ if (d * lights.data[i].inv_radius < 1.0) {
vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy);
vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular);
- float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x);
+ float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x);
vec3 spot_dir = lights.data[i].direction;
vec2 spot_att_angle = unpackHalf2x16(lights.data[i].cone_attenuation_angle);