diff options
Diffstat (limited to 'servers/rendering/renderer_rd/environment/sky.cpp')
-rw-r--r-- | servers/rendering/renderer_rd/environment/sky.cpp | 242 |
1 files changed, 113 insertions, 129 deletions
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index d7eb0287d8..ebf3c5f619 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -236,16 +236,16 @@ void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineC // Update uniform sets. { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.uniform_set, SKY_SET_UNIFORMS); if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) { // Material may not have a uniform set. - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, SKY_SET_MATERIAL); } - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, SKY_SET_TEXTURES); // Fog uniform set can be invalidated before drawing, so validate at draw time if (sky_scene_state.fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.fog_uniform_set)) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, 3); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.fog_uniform_set, SKY_SET_FOG); } else { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.default_fog_uniform_set, 3); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, sky_scene_state.default_fog_uniform_set, SKY_SET_FOG); } } @@ -738,6 +738,7 @@ void SkyRD::init() { sky_scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_scene_state.max_directional_lights) + "\n"; + defines += "\n#define SAMPLERS_BINDING_FIRST_INDEX " + itos(SAMPLERS_BINDING_FIRST_INDEX) + "\n"; // Initialize sky Vector<String> sky_modes; @@ -806,13 +807,12 @@ void SkyRD::init() { actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS"; actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS"; actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS"; - actions.custom_samplers["RADIANCE"] = "material_samplers[3]"; + actions.custom_samplers["RADIANCE"] = "SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP"; actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n"; actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n"; actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n"; actions.render_mode_defines["use_debanding"] = "#define USE_DEBANDING\n"; - actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; actions.texture_layout_set = 1; actions.base_uniform_string = "material."; @@ -853,28 +853,6 @@ void sky() { Vector<RD::Uniform> uniforms; { - Vector<RID> ids; - ids.resize(12); - RID *ids_ptr = ids.ptrw(); - ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - - RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 0, ids); - - uniforms.push_back(u); - } - - { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; @@ -898,6 +876,8 @@ void sky() { uniforms.push_back(u); } + uniforms.append_array(material_storage->get_default_sampler_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); + sky_scene_state.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_UNIFORMS); } @@ -1041,25 +1021,27 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con material = nullptr; } } + } - if (!material) { - sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); - } + if (!material) { + sky_material = sky_shader.default_material; + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); + } - ERR_FAIL_COND(!material); + ERR_FAIL_COND(!material); - shader_data = material->shader_data; + shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); + ERR_FAIL_COND(!shader_data); - material->set_as_used(); + material->set_as_used(); - // Save our screen size, our buffers will already have been cleared + if (sky) { + // Save our screen size; our buffers will already have been cleared. sky->screen_size.x = p_screen_size.x < 4 ? 4 : p_screen_size.x; sky->screen_size.y = p_screen_size.y < 4 ? 4 : p_screen_size.y; - // Trigger updating radiance buffers + // Trigger updating radiance buffers. if (sky->radiance.is_null()) { invalidate_sky(sky); update_dirty_skys(); @@ -1085,107 +1067,109 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con sky->prev_position = p_cam_transform.origin; sky->reflection.dirty = true; } + } + + sky_scene_state.ubo.directional_light_count = 0; + if (shader_data->uses_light) { + // 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++) { + if (!light_storage->owns_light_instance(p_lights[i])) { + continue; + } + RID base = light_storage->light_instance_get_base_light(p_lights[i]); + + ERR_CONTINUE(base.is_null()); + + RS::LightType type = light_storage->light_get_type(base); + if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) { + SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count]; + Transform3D light_transform = light_storage->light_instance_get_base_transform(p_lights[i]); + 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 = light_storage->light_is_negative(base) ? -1 : 1; + sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); - sky_scene_state.ubo.directional_light_count = 0; - if (shader_data->uses_light) { - // 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++) { - if (!light_storage->owns_light_instance(p_lights[i])) { - continue; + if (p_scene_render->is_using_physical_light_units()) { + sky_light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY); } - RID base = light_storage->light_instance_get_base_light(p_lights[i]); - - ERR_CONTINUE(base.is_null()); - - RS::LightType type = light_storage->light_get_type(base); - if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) { - SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count]; - Transform3D light_transform = light_storage->light_instance_get_base_transform(p_lights[i]); - 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 = light_storage->light_is_negative(base) ? -1 : 1; - sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); - - if (p_scene_render->is_using_physical_light_units()) { - sky_light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY); - } - - if (p_camera_attributes.is_valid()) { - sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes); - } - - Color linear_col = light_storage->light_get_color(base).srgb_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 = light_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::deg_to_rad(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; - } + + if (p_camera_attributes.is_valid()) { + sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes); } - } - // Check whether the directional_light_buffer changes - bool light_data_dirty = false; - - // 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; - sky_scene_state.last_frame_directional_lights[i].enabled = false; + + Color linear_col = light_storage->light_get_color(base).srgb_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 = light_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 about + // is expanding until we reach the radius of the near plane. There can't be more occluders than that. + angular_diameter = Math::tan(Math::deg_to_rad(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; + + // 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; + sky_scene_state.last_frame_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] || - sky_scene_state.directional_lights[i].direction[1] != sky_scene_state.last_frame_directional_lights[i].direction[1] || - sky_scene_state.directional_lights[i].direction[2] != sky_scene_state.last_frame_directional_lights[i].direction[2] || - sky_scene_state.directional_lights[i].energy != sky_scene_state.last_frame_directional_lights[i].energy || - sky_scene_state.directional_lights[i].color[0] != sky_scene_state.last_frame_directional_lights[i].color[0] || - sky_scene_state.directional_lights[i].color[1] != sky_scene_state.last_frame_directional_lights[i].color[1] || - sky_scene_state.directional_lights[i].color[2] != sky_scene_state.last_frame_directional_lights[i].color[2] || - sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled || - sky_scene_state.directional_lights[i].size != sky_scene_state.last_frame_directional_lights[i].size) { - light_data_dirty = true; - break; - } + 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] || + sky_scene_state.directional_lights[i].direction[1] != sky_scene_state.last_frame_directional_lights[i].direction[1] || + sky_scene_state.directional_lights[i].direction[2] != sky_scene_state.last_frame_directional_lights[i].direction[2] || + sky_scene_state.directional_lights[i].energy != sky_scene_state.last_frame_directional_lights[i].energy || + sky_scene_state.directional_lights[i].color[0] != sky_scene_state.last_frame_directional_lights[i].color[0] || + sky_scene_state.directional_lights[i].color[1] != sky_scene_state.last_frame_directional_lights[i].color[1] || + sky_scene_state.directional_lights[i].color[2] != sky_scene_state.last_frame_directional_lights[i].color[2] || + sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled || + sky_scene_state.directional_lights[i].size != sky_scene_state.last_frame_directional_lights[i].size) { + light_data_dirty = true; + break; } } + } - if (light_data_dirty) { - RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights); + if (light_data_dirty) { + RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights); - SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights; - sky_scene_state.last_frame_directional_lights = sky_scene_state.directional_lights; - sky_scene_state.directional_lights = temp; - sky_scene_state.last_frame_directional_light_count = sky_scene_state.ubo.directional_light_count; + SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights; + sky_scene_state.last_frame_directional_lights = sky_scene_state.directional_lights; + sky_scene_state.directional_lights = temp; + sky_scene_state.last_frame_directional_light_count = sky_scene_state.ubo.directional_light_count; + if (sky) { sky->reflection.dirty = true; } } } - //setup fog variables + // Setup fog variables. sky_scene_state.ubo.volumetric_fog_enabled = false; if (p_render_buffers.is_valid()) { if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { @@ -1199,7 +1183,7 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con sky_scene_state.ubo.volumetric_fog_inv_length = 1.0; } - float fog_detail_spread = fog->spread; //reverse lookup + float fog_detail_spread = fog->spread; // Reverse lookup. if (fog_detail_spread > 0.0) { sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread; } else { @@ -1212,9 +1196,9 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con sky_scene_state.view_count = p_view_count; sky_scene_state.cam_transform = p_cam_transform; - sky_scene_state.cam_projection = p_cam_projection; // We only use this when rendering a single view + sky_scene_state.cam_projection = p_cam_projection; // We only use this when rendering a single view. - // Our info in our UBO is only used if we're rendering stereo + // Our info in our UBO is only used if we're rendering stereo. for (uint32_t i = 0; i < p_view_count; i++) { Projection view_inv_projection = p_view_projections[i].inverse(); if (p_view_count > 1) { @@ -1231,7 +1215,7 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con sky_scene_state.ubo.view_eye_offsets[i][3] = 0.0; } - sky_scene_state.ubo.z_far = p_view_projections[0].get_z_far(); // Should be the same for all projection + sky_scene_state.ubo.z_far = p_view_projections[0].get_z_far(); // Should be the same for all projection. sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_env); sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_env); sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_env); |