1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-12 13:20:55 +00:00

Update Sky lights in sky setup function

This commit is contained in:
clayjohn
2022-01-23 15:06:49 -08:00
parent 81c28dd706
commit 430d5d64aa
5 changed files with 63 additions and 45 deletions

View File

@@ -1039,8 +1039,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);
@@ -1121,15 +1121,67 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
}
if (shader_data->uses_light) {
// Check whether the directional_light_buffer changes
bool light_data_dirty = false;
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 = 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] ||