diff options
Diffstat (limited to 'servers/rendering/renderer_scene_cull.cpp')
-rw-r--r-- | servers/rendering/renderer_scene_cull.cpp | 156 |
1 files changed, 101 insertions, 55 deletions
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 348f6e4695..813c1fa4ff 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -1,36 +1,37 @@ -/*************************************************************************/ -/* renderer_scene_cull.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* renderer_scene_cull.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #include "renderer_scene_cull.h" #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "core/os/os.h" #include "rendering_server_default.h" #include "rendering_server_globals.h" @@ -646,6 +647,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { geom->geometry_instance->set_surface_materials(instance->materials); geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb); geom->geometry_instance->set_layer_mask(instance->layer_mask); + geom->geometry_instance->set_pivot_data(instance->sorting_offset, instance->use_aabb_center); geom->geometry_instance->set_lod_bias(instance->lod_bias); geom->geometry_instance->set_transparency(instance->transparency); geom->geometry_instance->set_use_baked_light(instance->baked_light); @@ -693,6 +695,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { instance->base_data = decal; decal->instance = RSG::texture_storage->decal_instance_create(p_base); + RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset); } break; case RS::INSTANCE_LIGHTMAP: { InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData); @@ -747,6 +750,10 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) { switch (instance->base_type) { case RS::INSTANCE_LIGHT: { InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); + if (instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + instance->scenario->dynamic_lights.erase(light->instance); + } + #ifdef DEBUG_ENABLED if (light->geometries.size()) { ERR_PRINT("BUG, indexing did not unpair geometries from light."); @@ -832,6 +839,10 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); + if (instance->layer_mask == p_mask) { + return; + } + instance->layer_mask = p_mask; if (instance->scenario && instance->array_index >= 0) { instance->scenario->instance_data[instance->array_index].layer_mask = p_mask; @@ -841,6 +852,30 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); ERR_FAIL_NULL(geom->geometry_instance); geom->geometry_instance->set_layer_mask(p_mask); + + if (geom->can_cast_shadows) { + for (HashSet<RendererSceneCull::Instance *>::Iterator I = geom->lights.begin(); I != geom->lights.end(); ++I) { + InstanceLightData *light = static_cast<InstanceLightData *>((*I)->base_data); + light->shadow_dirty = true; + } + } + } +} + +void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_offset, bool p_use_aabb_center) { + Instance *instance = instance_owner.get_or_null(p_instance); + ERR_FAIL_COND(!instance); + + instance->sorting_offset = p_sorting_offset; + instance->use_aabb_center = p_use_aabb_center; + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + ERR_FAIL_NULL(geom->geometry_instance); + geom->geometry_instance->set_pivot_data(p_sorting_offset, p_use_aabb_center); + } else if (instance->base_type == RS::INSTANCE_DECAL && instance->base_data) { + InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data); + RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset); } } @@ -1753,6 +1788,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { pair.pair_allocator = &pair_allocator; pair.pair_pass = pair_pass; pair.pair_mask = 0; + pair.cull_mask = 0xFFFFFFFF; if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { pair.pair_mask |= 1 << RS::INSTANCE_LIGHT; @@ -1773,12 +1809,14 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI); pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES]; } + pair.cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base); } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) { pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (p_instance->base_type == RS::INSTANCE_DECAL)) { pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; + pair.cull_mask = RSG::texture_storage->decal_get_cull_mask(p_instance->base); } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { pair.pair_mask = (1 << RS::INSTANCE_PARTICLES); pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; @@ -2238,7 +2276,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in } } -bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) { +bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold, uint32_t p_visible_layers) { InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); Transform3D light_transform = p_instance->transform; @@ -2294,7 +2332,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { continue; } else { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { @@ -2372,7 +2410,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { continue; } else { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { @@ -2435,7 +2473,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows || !(p_visible_layers & instance->layer_mask)) { continue; } else { if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { @@ -2512,7 +2550,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu } break; } - camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter); + camera_data.set_camera(transform, projection, is_orthogonal, vaspect, jitter, camera->visible_layers); } else { // Setup our camera for our XR interface. // We can support multiple views here each with their own camera @@ -2520,7 +2558,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu Projection projections[RendererSceneRender::MAX_RENDER_VIEWS]; uint32_t view_count = p_xr_interface->get_view_count(); - ERR_FAIL_COND_MSG(view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported"); + ERR_FAIL_COND_MSG(view_count == 0 || view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported"); float aspect = p_viewport_size.width / (float)p_viewport_size.height; @@ -2534,7 +2572,7 @@ void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_bu } if (view_count == 1) { - camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter); + camera_data.set_camera(transforms[0], projections[0], false, camera->vaspect, jitter, camera->visible_layers); } else if (view_count == 2) { camera_data.set_multiview_camera(view_count, transforms, projections, false, camera->vaspect); } else { @@ -2794,7 +2832,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); ERR_FAIL_NULL(geom->geometry_instance); + cull_data.cull->lock.lock(); geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0); + cull_data.cull->lock.unlock(); idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY); } @@ -2861,7 +2901,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed)); } ERR_FAIL_NULL(geom->geometry_instance); + cull_data.cull->lock.lock(); geom->geometry_instance->set_lightmap_capture(sh); + cull_data.cull->lock.unlock(); idata.instance->last_frame_pass = frame_number; } @@ -2876,7 +2918,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul if (IN_FRUSTUM(cull_data.cull->shadows[j].cascades[k].frustum) && VIS_CHECK) { uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK; - if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) { + if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS && LAYER_CHECK) { cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry); mesh_visible = true; } @@ -2926,11 +2968,13 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c Scenario *scenario = scenario_owner.get_or_null(p_scenario); + ERR_FAIL_COND(p_render_buffers.is_null()); + render_pass++; scene_render->set_scene_pass(render_pass); - if (p_render_buffers.is_valid()) { + if (p_reflection_probe.is_null()) { //no rendering code here, this is only to set up what needs to be done, request regions, etc. scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not) } @@ -3012,7 +3056,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c { //sdfgi cull.sdfgi.region_count = 0; - if (p_render_buffers.is_valid()) { + if (p_reflection_probe.is_null()) { cull.sdfgi.cascade_light_count = 0; uint32_t prev_cascade = 0xFFFFFFFF; @@ -3058,15 +3102,15 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c #endif if (cull_to > thread_cull_threshold) { //multiple threads - for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { - scene_cull_result_threads[i].clear(); + for (InstanceCullResult &thread : scene_cull_result_threads) { + thread.clear(); } WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_scene_cull_threaded, &cull_data, scene_cull_result_threads.size(), -1, true, SNAME("RenderCullInstances")); WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); - for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { - scene_cull_result.append_from(scene_cull_result_threads[i]); + for (InstanceCullResult &thread : scene_cull_result_threads) { + scene_cull_result.append_from(thread); } } else { @@ -3203,7 +3247,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) { //must redraw! RENDER_TIMESTAMP("> Render Light3D " + itos(i)); - light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold); + light->shadow_dirty = _light_instance_update_shadow(ins, p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect, p_shadow_atlas, scenario, p_screen_mesh_lod_threshold, p_visible_layers); RENDER_TIMESTAMP("< Render Light3D " + itos(i)); } else { light->shadow_dirty = redraw; @@ -3214,6 +3258,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c //render SDFGI { + // Q: Should this whole block be skipped if we're rendering our reflection probe? + sdfgi_update_data.update_static = false; if (cull.sdfgi.region_count > 0) { @@ -3239,7 +3285,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } } - if (p_render_buffers.is_valid()) { + if (p_reflection_probe.is_null()) { sdfgi_update_data.directional_lights = &directional_lights; sdfgi_update_data.positional_light_instances = scenario->dynamic_lights.ptr(); sdfgi_update_data.positional_light_count = scenario->dynamic_lights.size(); @@ -3319,7 +3365,7 @@ void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_rend RendererSceneRender::CameraData camera_data; camera_data.set_camera(Transform3D(), Projection(), true, false); - scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); + scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), environment, RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr); #endif } @@ -3354,13 +3400,13 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int Vector3(0, -1, 0) }; - Vector3 extents = RSG::light_storage->reflection_probe_get_extents(p_instance->base); + Vector3 probe_size = RSG::light_storage->reflection_probe_get_size(p_instance->base); Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base); float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base); - float size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas); - float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size; + float atlas_size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas); + float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / atlas_size; - Vector3 edge = view_normals[p_step] * extents; + Vector3 edge = view_normals[p_step] * probe_size / 2; float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit max_distance = MAX(max_distance, distance); @@ -3392,7 +3438,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int RendererSceneRender::CameraData camera_data; camera_data.set_camera(xform, cm, false, false); - Ref<RenderSceneBuffers> render_buffers; + Ref<RenderSceneBuffers> render_buffers = RSG::light_storage->reflection_probe_atlas_get_render_buffers(scenario->reflection_atlas); _render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows); } else { @@ -4094,8 +4140,8 @@ RendererSceneCull::RendererSceneCull() { scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count()); - for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { - scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); + for (InstanceCullResult &thread : scene_cull_result_threads) { + thread.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); } indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame"); @@ -4123,8 +4169,8 @@ RendererSceneCull::~RendererSceneCull() { } scene_cull_result.reset(); - for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { - scene_cull_result_threads[i].reset(); + for (InstanceCullResult &thread : scene_cull_result_threads) { + thread.reset(); } scene_cull_result_threads.clear(); |