diff options
5 files changed, 62 insertions, 44 deletions
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 87301a9d3a..5d84edfc67 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1390,7 +1390,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co projection = correction * p_render_data->cam_projection; } - sky.setup(env, p_render_data->render_buffers, projection, p_render_data->cam_transform, screen_size, this); + sky.setup(env, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this); RID sky_rid = env->sky; if (sky_rid.is_valid()) { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 778d7baa5d..a623af7533 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -633,7 +633,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color projection = correction * p_render_data->cam_projection; } - sky.setup(env, p_render_data->render_buffers, projection, p_render_data->cam_transform, screen_size, this); + sky.setup(env, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this); RID sky_rid = env->sky; if (sky_rid.is_valid()) { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 43a1812f89..2d34d2a2a0 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -3263,7 +3263,6 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const r_directional_light_count = 0; r_positional_light_count = 0; - sky.sky_scene_state.ubo.directional_light_count = 0; Plane camera_plane(-p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized(), p_camera_transform.origin); @@ -3284,43 +3283,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const RS::LightType type = storage->light_get_type(base); switch (type) { case RS::LIGHT_DIRECTIONAL: { - // Copy to SkyDirectionalLightData - if (r_directional_light_count < sky.sky_scene_state.max_directional_lights) { - RendererSceneSkyRD::SkyDirectionalLightData &sky_light_data = sky.sky_scene_state.directional_lights[r_directional_light_count]; - Transform3D light_transform = li->transform; - Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); - - sky_light_data.direction[0] = world_direction.x; - sky_light_data.direction[1] = world_direction.y; - sky_light_data.direction[2] = -world_direction.z; - - float sign = storage->light_is_negative(base) ? -1 : 1; - sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); - - Color linear_col = storage->light_get_color(base).to_linear(); - sky_light_data.color[0] = linear_col.r; - sky_light_data.color[1] = linear_col.g; - sky_light_data.color[2] = linear_col.b; - - sky_light_data.enabled = true; - - float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); - if (angular_diameter > 0.0) { - // I know tan(0) is 0, but let's not risk it with numerical precision. - // technically this will keep expanding until reaching the sun, but all we care - // is expand until we reach the radius of the near plane (there can't be more occluders than that) - angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); - if (storage->light_has_shadow(base)) { - r_directional_light_soft_shadows = true; - } - } else { - angular_diameter = 0.0; - } - sky_light_data.size = angular_diameter; - sky.sky_scene_state.ubo.directional_light_count++; - } - - if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_is_sky_only(base)) { + if (r_directional_light_count >= cluster.max_directional_lights) { continue; } @@ -3397,6 +3360,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const // technically this will keep expanding until reaching the sun, but all we care // is expand until we reach the radius of the near plane (there can't be more occluders than that) angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + if (storage->light_has_shadow(base)) { + r_directional_light_soft_shadows = true; + } } else { angular_diameter = 0.0; } diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index f6f39230f8..fb36190c3e 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -1040,8 +1040,8 @@ RendererSceneSkyRD::~RendererSceneSkyRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency } -void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { - ERR_FAIL_COND(!p_env); // I guess without an environment we also can't have a sky... +void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { + ERR_FAIL_COND(!p_env); SkyMaterialData *material = nullptr; Sky *sky = get_sky(p_env->sky); @@ -1122,15 +1122,67 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b } if (shader_data->uses_light) { + sky_scene_state.ubo.directional_light_count = 0; + // Run through the list of lights in the scene and pick out the Directional Lights. + // This can't be done in RenderSceneRenderRD::_setup lights because that needs to be called + // after the depth prepass, but this runs before the depth prepass + for (int i = 0; i < (int)p_lights.size(); i++) { + RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_lights[i]); + if (!li) { + continue; + } + RID base = li->light; + + ERR_CONTINUE(base.is_null()); + + RS::LightType type = storage->light_get_type(base); + if (type == RS::LIGHT_DIRECTIONAL) { + SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count]; + Transform3D light_transform = li->transform; + Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); + + sky_light_data.direction[0] = world_direction.x; + sky_light_data.direction[1] = world_direction.y; + sky_light_data.direction[2] = -world_direction.z; + + float sign = storage->light_is_negative(base) ? -1 : 1; + sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); + + Color linear_col = storage->light_get_color(base).to_linear(); + sky_light_data.color[0] = linear_col.r; + sky_light_data.color[1] = linear_col.g; + sky_light_data.color[2] = linear_col.b; + + sky_light_data.enabled = true; + + float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); + if (angular_diameter > 0.0) { + // I know tan(0) is 0, but let's not risk it with numerical precision. + // technically this will keep expanding until reaching the sun, but all we care + // is expand until we reach the radius of the near plane (there can't be more occluders than that) + angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + } else { + angular_diameter = 0.0; + } + sky_light_data.size = angular_diameter; + sky_scene_state.ubo.directional_light_count++; + if (sky_scene_state.ubo.directional_light_count >= sky_scene_state.max_directional_lights) { + break; + } + } + } // Check whether the directional_light_buffer changes - bool light_data_dirty = false; + bool light_data_dirty = true; + // Light buffer is dirty if we have fewer or more lights + // If we have fewer lights, make sure that old lights are disabled if (sky_scene_state.ubo.directional_light_count != sky_scene_state.last_frame_directional_light_count) { light_data_dirty = true; for (uint32_t i = sky_scene_state.ubo.directional_light_count; i < sky_scene_state.max_directional_lights; i++) { sky_scene_state.directional_lights[i].enabled = false; } } + if (!light_data_dirty) { for (uint32_t i = 0; i < sky_scene_state.ubo.directional_light_count; i++) { if (sky_scene_state.directional_lights[i].direction[0] != sky_scene_state.last_frame_directional_lights[i].direction[0] || diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index d81a415c2d..13d24e2508 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -292,7 +292,7 @@ public: void set_texture_format(RD::DataFormat p_texture_format); ~RendererSceneSkyRD(); - void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); + void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); |