diff options
Diffstat (limited to 'servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp')
-rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp | 58 |
1 files changed, 55 insertions, 3 deletions
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] || |