diff options
Diffstat (limited to 'servers/rendering/rendering_server_scene.cpp')
-rw-r--r-- | servers/rendering/rendering_server_scene.cpp | 141 |
1 files changed, 124 insertions, 17 deletions
diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp index 7b8504036e..75a5834791 100644 --- a/servers/rendering/rendering_server_scene.cpp +++ b/servers/rendering/rendering_server_scene.cpp @@ -369,6 +369,11 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) { switch (instance->base_type) { case RS::INSTANCE_LIGHT: { InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); + + if (RSG::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."); @@ -976,7 +981,26 @@ void RenderingServerScene::_update_instance(Instance *p_instance) { InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); RSG::scene_render->light_instance_set_transform(light->instance, p_instance->transform); + RSG::scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb)); light->shadow_dirty = true; + + RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base); + if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) { + if (light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + p_instance->scenario->dynamic_lights.erase(light->instance); + } + + light->bake_mode = bake_mode; + + if (light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + p_instance->scenario->dynamic_lights.push_back(light->instance); + } + } + + uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base); + if (light->max_sdfgi_cascade != max_sdfgi_cascade) { + light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario + } } if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) { @@ -1788,8 +1812,10 @@ void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID } break; } - _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); - _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); + RID environment = _render_get_environment(p_camera, p_scenario); + + _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); #endif } @@ -1808,6 +1834,8 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface> Transform world_origin = XRServer::get_singleton()->get_world_origin(); Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin); + RID environment = _render_get_environment(p_camera, p_scenario); + // For stereo render we only prepare for our left eye and then reuse the outcome for our right eye if (p_eye == XRInterface::EYE_LEFT) { // Center our transform, we assume basis is equal. @@ -1865,17 +1893,17 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface> mono_transform *= apply_z_shift; // now prepare our scene with our adjusted transform projection matrix - _prepare_scene(mono_transform, combined_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + _prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); } else if (p_eye == XRInterface::EYE_MONO) { // For mono render, prepare as per usual - _prepare_scene(cam_transform, camera_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + _prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); } // And render our scene... - _render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); + _render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); }; -void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) { +void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) { // Note, in stereo rendering: // - p_cam_transform will be a transform in the middle of our two eyes // - p_cam_projection is a wider frustrum that encompasses both eyes @@ -1887,6 +1915,10 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const RSG::scene_render->set_scene_pass(render_pass); + if (p_render_buffers.is_valid()) { + RSG::scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not) + } + RENDER_TIMESTAMP("Frustum Culling"); //rasterizer->set_camera(camera->transform, camera_matrix,ortho); @@ -2224,22 +2256,97 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const } } } + + /* UPDATE SDFGI */ + + if (p_render_buffers.is_valid()) { + uint32_t cascade_index[8]; + uint32_t cascade_sizes[8]; + const RID *cascade_ptrs[8]; + uint32_t cascade_count = 0; + uint32_t sdfgi_light_cull_count = 0; + + uint32_t prev_cascade = 0xFFFFFFFF; + for (int i = 0; i < RSG::scene_render->sdfgi_get_pending_region_count(p_render_buffers); i++) { + AABB region = RSG::scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i); + uint32_t region_cascade = RSG::scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i); + + if (region_cascade != prev_cascade) { + cascade_sizes[cascade_count] = 0; + cascade_index[cascade_count] = region_cascade; + cascade_ptrs[cascade_count] = &sdfgi_light_cull_result[sdfgi_light_cull_count]; + cascade_count++; + sdfgi_light_cull_pass++; + prev_cascade = region_cascade; + } + uint32_t sdfgi_cull_count = scenario->octree.cull_aabb(region, instance_shadow_cull_result, MAX_INSTANCE_CULL); + + for (uint32_t j = 0; j < sdfgi_cull_count; j++) { + Instance *ins = instance_shadow_cull_result[j]; + + bool keep = false; + + if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) { + InstanceLightData *instance_light = (InstanceLightData *)ins->base_data; + if (instance_light->bake_mode != RS::LIGHT_BAKE_STATIC || region_cascade > instance_light->max_sdfgi_cascade) { + continue; + } + + if (sdfgi_light_cull_pass != instance_light->sdfgi_cascade_light_pass && sdfgi_light_cull_count < MAX_LIGHTS_CULLED) { + instance_light->sdfgi_cascade_light_pass = sdfgi_light_cull_pass; + sdfgi_light_cull_result[sdfgi_light_cull_count++] = instance_light->instance; + cascade_sizes[cascade_count - 1]++; + } + } else if ((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + if (ins->baked_light) { + keep = true; + } + } + + if (!keep) { + // remove, no reason to keep + sdfgi_cull_count--; + SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[sdfgi_cull_count]); + j--; + } + } + + RSG::scene_render->render_sdfgi(p_render_buffers, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, sdfgi_cull_count); + //have to save updated cascades, then update static lights. + } + + if (sdfgi_light_cull_count) { + RSG::scene_render->render_sdfgi_static_lights(p_render_buffers, cascade_count, cascade_index, cascade_ptrs, cascade_sizes); + } + + RSG::scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_light_ptr, directional_light_count, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size()); + } } -void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { - Scenario *scenario = scenario_owner.getornull(p_scenario); +RID RenderingServerScene::_render_get_environment(RID p_camera, RID p_scenario) { + Camera *camera = camera_owner.getornull(p_camera); + if (camera && RSG::scene_render->is_environment(camera->env)) { + return camera->env; + } - /* ENVIRONMENT */ + Scenario *scenario = scenario_owner.getornull(p_scenario); + if (!scenario) { + return RID(); + } + if (RSG::scene_render->is_environment(scenario->environment)) { + return scenario->environment; + } - RID environment; - if (p_force_environment.is_valid()) { //camera has more environment priority - environment = p_force_environment; - } else if (scenario->environment.is_valid()) { - environment = scenario->environment; - } else { - environment = scenario->fallback_environment; + if (RSG::scene_render->is_environment(scenario->fallback_environment)) { + return scenario->fallback_environment; } + return RID(); +} + +void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + RID camera_effects; if (p_force_camera_effects.is_valid()) { camera_effects = p_force_camera_effects; @@ -2249,7 +2356,7 @@ void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p /* PROCESS GEOMETRY AND DRAW SCENE */ RENDER_TIMESTAMP("Render Scene "); - RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); + RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); } void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) { |