diff options
Diffstat (limited to 'servers/rendering/renderer_rd/environment')
| -rw-r--r-- | servers/rendering/renderer_rd/environment/fog.cpp | 117 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/environment/fog.h | 64 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/environment/gi.cpp | 466 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/environment/gi.h | 229 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/environment/sky.cpp | 115 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/environment/sky.h | 54 | 
6 files changed, 615 insertions, 430 deletions
| diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 257b67cf04..eece195946 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -57,12 +57,19 @@ void Fog::fog_volume_initialize(RID p_rid) {  	fog_volume_owner.initialize_rid(p_rid, FogVolume());  } -void Fog::fog_free(RID p_rid) { +void Fog::fog_volume_free(RID p_rid) {  	FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);  	fog_volume->dependency.deleted_notify(p_rid);  	fog_volume_owner.free(p_rid);  } +Dependency *Fog::fog_volume_get_dependency(RID p_fog_volume) const { +	FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); +	ERR_FAIL_NULL_V(fog_volume, nullptr); + +	return &fog_volume->dependency; +} +  void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {  	FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);  	ERR_FAIL_COND(!fog_volume); @@ -122,8 +129,6 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const {  			return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));  		}  	} - -	return AABB();  }  Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { @@ -138,7 +143,7 @@ Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const {  bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {  	uniform_set_updated = true; -	return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL); +	return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true);  }  Fog::FogMaterialData::~FogMaterialData() { @@ -361,7 +366,7 @@ void Fog::FogShaderData::set_code(const String &p_code) {  	valid = true;  } -void Fog::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void Fog::FogShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {  	if (!p_texture.is_valid()) {  		if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {  			default_texture_params[p_name].erase(p_index); @@ -430,7 +435,7 @@ void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::I  	}  } -bool Fog::FogShaderData::is_param_texture(const StringName &p_param) const { +bool Fog::FogShaderData::is_parameter_texture(const StringName &p_param) const {  	if (!uniforms.has(p_param)) {  		return false;  	} @@ -473,7 +478,7 @@ Fog::FogShaderData::~FogShaderData() {  ////////////////////////////////////////////////////////////////////////////////  // Volumetric Fog -Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) { +void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) {  	width = fog_size.x;  	height = fog_size.y;  	depth = fog_size.z; @@ -591,6 +596,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  	RENDER_TIMESTAMP("> Volumetric Fog");  	RD::get_singleton()->draw_command_begin_label("Volumetric Fog"); +	Ref<VolumetricFog> fog = p_settings.vfog; +  	if (p_fog_volumes.size() > 0) {  		RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes"); @@ -623,9 +630,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  		params.z_far = z_far;  		params.time = p_settings.time; -		params.fog_volume_size[0] = p_settings.vfog->width; -		params.fog_volume_size[1] = p_settings.vfog->height; -		params.fog_volume_size[2] = p_settings.vfog->depth; +		params.fog_volume_size[0] = fog->width; +		params.fog_volume_size[1] = fog->height; +		params.fog_volume_size[2] = fog->depth;  		params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env);  		params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; @@ -638,7 +645,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  		RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); -		if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) { +		if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {  			Vector<RD::Uniform> uniforms;  			{ @@ -649,7 +656,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  #endif  				u.binding = 1; -				u.append_id(p_settings.vfog->emissive_map); +				u.append_id(fog->emissive_map);  				uniforms.push_back(u);  			} @@ -669,7 +676,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  #endif  				u.binding = 3; -				u.append_id(p_settings.vfog->density_map); +				u.append_id(fog->density_map);  				uniforms.push_back(u);  			} @@ -681,11 +688,11 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  #endif  				u.binding = 4; -				u.append_id(p_settings.vfog->light_map); +				u.append_id(fog->light_map);  				uniforms.push_back(u);  			} -			p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); +			fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);  		}  		RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -720,9 +727,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			any_uses_time |= shader_data->uses_time; -			Vector3i min = Vector3i(); -			Vector3i max = Vector3i(); -			Vector3i kernel_size = Vector3i(); +			Vector3i min; +			Vector3i max; +			Vector3i kernel_size;  			Vector3 position = fog_volume_instance->transform.get_origin();  			RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); @@ -731,7 +738,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {  				// Local fog volume.  				Vector3i points[8]; -				Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); +				Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth);  				float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);  				points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);  				points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); @@ -742,7 +749,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  				points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);  				points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); -				min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1); +				min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);  				max = Vector3i(1, 1, 1);  				for (int j = 0; j < 8; j++) { @@ -753,9 +760,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  				kernel_size = max - min;  			} else {  				// Volume type global runs on all cells -				extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); +				extents = Vector3(fog->width, fog->height, fog->depth);  				min = Vector3i(0, 0, 0); -				kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth)); +				kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth));  			}  			if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) { @@ -777,7 +784,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); -			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); +			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);  			RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant));  			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);  			if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. @@ -795,7 +802,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  		RD::get_singleton()->compute_list_end();  	} -	if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) { +	if (fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->process_uniform_set_density)) {  		//re create uniform set if needed  		Vector<RD::Uniform> uniforms;  		Vector<RD::Uniform> copy_uniforms; @@ -875,7 +882,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  			u.binding = 8; -			u.append_id(p_settings.vfog->light_density_map); +			u.append_id(fog->light_density_map);  			uniforms.push_back(u);  			copy_uniforms.push_back(u);  		} @@ -884,7 +891,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  			u.binding = 9; -			u.append_id(p_settings.vfog->fog_map); +			u.append_id(fog->fog_map);  			uniforms.push_back(u);  		} @@ -892,7 +899,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  			u.binding = 9; -			u.append_id(p_settings.vfog->prev_light_density_map); +			u.append_id(fog->prev_light_density_map);  			copy_uniforms.push_back(u);  		} @@ -909,7 +916,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;  			u.binding = 11; -			u.append_id(p_settings.voxel_gl_buffer); +			u.append_id(p_settings.voxel_gi_buffer);  			uniforms.push_back(u);  			copy_uniforms.push_back(u);  		} @@ -944,7 +951,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			u.binding = 15; -			u.append_id(p_settings.vfog->prev_light_density_map); +			u.append_id(fog->prev_light_density_map);  			uniforms.push_back(u);  		}  		{ @@ -955,7 +962,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  #endif  			u.binding = 16; -			u.append_id(p_settings.vfog->density_map); +			u.append_id(fog->density_map);  			uniforms.push_back(u);  		}  		{ @@ -966,7 +973,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  #endif  			u.binding = 17; -			u.append_id(p_settings.vfog->light_map); +			u.append_id(fog->light_map);  			uniforms.push_back(u);  		} @@ -978,7 +985,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  #endif  			u.binding = 18; -			u.append_id(p_settings.vfog->emissive_map); +			u.append_id(fog->emissive_map);  			uniforms.push_back(u);  		} @@ -992,9 +999,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  			uniforms.push_back(u);  		} -		p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); +		fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); -		p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); +		fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);  		RID aux7 = uniforms.write[7].get_id(0);  		RID aux8 = uniforms.write[8].get_id(0); @@ -1002,17 +1009,17 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  		uniforms.write[7].set_id(0, aux8);  		uniforms.write[8].set_id(0, aux7); -		p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); +		fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);  		uniforms.remove_at(8);  		uniforms.write[7].set_id(0, aux7); -		p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); +		fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);  	} -	bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi != nullptr); +	bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi.is_valid());  	if (using_sdfgi) { -		if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) { +		if (fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->sdfgi_uniform_set)) {  			Vector<RD::Uniform> uniforms;  			{ @@ -1039,12 +1046,12 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  				uniforms.push_back(u);  			} -			p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); +			fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);  		}  	} -	p_settings.vfog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); -	p_settings.vfog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); +	fog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); +	fog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);  	VolumetricFogShader::ParamsUBO params; @@ -1079,9 +1086,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  	params.ambient_color[2] = ambient_color.b;  	params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env); -	params.fog_volume_size[0] = p_settings.vfog->width; -	params.fog_volume_size[1] = p_settings.vfog->height; -	params.fog_volume_size[2] = p_settings.vfog->depth; +	params.fog_volume_size[0] = fog->width; +	params.fog_volume_size[1] = fog->height; +	params.fog_volume_size[2] = fog->depth;  	params.directional_light_count = p_directional_light_count; @@ -1149,19 +1156,19 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]); -	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0); +	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set_density, 0);  	if (using_sdfgi) { -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1);  	} -	RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); +	RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);  	RD::get_singleton()->compute_list_add_barrier(compute_list);  	// Copy fog to history buffer  	if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {  		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]); -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0); -		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0); +		RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);  		RD::get_singleton()->compute_list_add_barrier(compute_list);  	}  	RD::get_singleton()->draw_command_end_label(); @@ -1172,8 +1179,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  		RENDER_TIMESTAMP("Filter Fog");  		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); -		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0); +		RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);  		RD::get_singleton()->compute_list_end();  		//need restart for buffer update @@ -1183,8 +1190,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  		compute_list = RD::get_singleton()->compute_list_begin();  		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0); -		RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set2, 0); +		RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);  		RD::get_singleton()->compute_list_add_barrier(compute_list);  		RD::get_singleton()->draw_command_end_label(); @@ -1194,8 +1201,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P  	RD::get_singleton()->draw_command_begin_label("Integrate Fog");  	RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]); -	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); -	RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1); +	RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0); +	RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1);  	RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 171f9f3b88..0ade995758 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -38,12 +38,17 @@  #include "servers/rendering/renderer_rd/environment/gi.h"  #include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"  #include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"  #include "servers/rendering/storage/utilities.h" +#define RB_SCOPE_FOG SNAME("Fog") +  namespace RendererRD {  class Fog : public RendererFog { -public: +private: +	static Fog *singleton; +  	/* FOG VOLUMES */  	struct FogVolume { @@ -55,16 +60,14 @@ public:  		Dependency dependency;  	}; +	mutable RID_Owner<FogVolume, true> fog_volume_owner; +  	struct FogVolumeInstance {  		RID volume;  		Transform3D transform;  		bool active = false;  	}; -private: -	static Fog *singleton; - -	mutable RID_Owner<FogVolume, true> fog_volume_owner;  	mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;  	/* Volumetric Fog */ @@ -199,10 +202,10 @@ private:  		virtual void set_path_hint(const String &p_hint);  		virtual void set_code(const String &p_Code); -		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); +		virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);  		virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;  		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; -		virtual bool is_param_texture(const StringName &p_param) const; +		virtual bool is_parameter_texture(const StringName &p_param) const;  		virtual bool is_animated() const;  		virtual bool casts_shadows() const;  		virtual Variant get_default_parameter(const StringName &p_parameter) const; @@ -237,12 +240,12 @@ public:  	/* FOG VOLUMES */ -	FogVolume *get_fog_volume(RID p_rid) { return fog_volume_owner.get_or_null(p_rid); };  	bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); };  	virtual RID fog_volume_allocate() override;  	virtual void fog_volume_initialize(RID p_rid) override; -	virtual void fog_free(RID p_rid) override; +	virtual void fog_volume_free(RID p_rid) override; +	Dependency *fog_volume_get_dependency(RID p_fog_volume) const;  	virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;  	virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; @@ -254,14 +257,40 @@ public:  	/* FOG VOLUMES INSTANCE */ -	FogVolumeInstance *get_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.get_or_null(p_rid); };  	bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); };  	RID fog_volume_instance_create(RID p_fog_volume);  	void fog_instance_free(RID p_rid); +	void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) { +		Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); +		ERR_FAIL_COND(!fvi); +		fvi->transform = p_transform; +	} + +	void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) { +		Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); +		ERR_FAIL_COND(!fvi); +		fvi->active = p_active; +	} + +	RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const { +		Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); +		ERR_FAIL_COND_V(!fvi, RID()); +		return fvi->volume; +	} + +	Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const { +		Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); +		ERR_FAIL_COND_V(!fvi, Vector3()); +		return fvi->transform.get_origin(); +	} +  	/* Volumetric FOG */ -	struct VolumetricFog { +	class VolumetricFog : public RenderBufferCustomDataRD { +		GDCLASS(VolumetricFog, RenderBufferCustomDataRD) + +	public:  		enum {  			MAX_TEMPORAL_FRAMES = 16  		}; @@ -290,7 +319,10 @@ public:  		int last_shadow_filter = -1; -		VolumetricFog(const Vector3i &fog_size, RID p_sky_shader); +		virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; +		virtual void free_data() override{}; + +		void init(const Vector3i &fog_size, RID p_sky_shader);  		~VolumetricFog();  	}; @@ -304,7 +336,7 @@ public:  		uint32_t max_cluster_elements;  		bool volumetric_fog_filter_active;  		RID shadow_sampler; -		RID voxel_gl_buffer; +		RID voxel_gi_buffer;  		RID shadow_atlas_depth;  		RID omni_light_buffer;  		RID spot_light_buffer; @@ -312,11 +344,11 @@ public:  		RID directional_light_buffer;  		// Objects related to our render buffer -		VolumetricFog *vfog; +		Ref<VolumetricFog> vfog;  		ClusterBuilderRD *cluster_builder;  		GI *gi; -		GI::SDFGI *sdfgi; -		GI::RenderBuffersGI *rbgi; +		Ref<GI::SDFGI> sdfgi; +		Ref<GI::RenderBuffersGI> rbgi;  		RID env;  		SkyRD *sky;  	}; diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index eaef5ba39c..550fe27e4c 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -34,6 +34,7 @@  #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"  #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"  #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"  #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"  #include "servers/rendering/rendering_server_default.h" @@ -287,6 +288,19 @@ float GI::voxel_gi_get_energy(RID p_voxel_gi) const {  	return voxel_gi->energy;  } +void GI::voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) { +	VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); +	ERR_FAIL_COND(!voxel_gi); + +	voxel_gi->baked_exposure = p_baked_exposure; +} + +float GI::voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const { +	VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); +	ERR_FAIL_COND_V(!voxel_gi, 0); +	return voxel_gi->baked_exposure; +} +  void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {  	VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);  	ERR_FAIL_COND(!voxel_gi); @@ -371,6 +385,13 @@ RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) {  	return voxel_gi->sdf_texture;  } +Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const { +	VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); +	ERR_FAIL_COND_V(!voxel_gi, nullptr); + +	return &voxel_gi->dependency; +} +  ////////////////////////////////////////////////////////////////////////////////  // SDFGI @@ -1108,7 +1129,11 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re  	reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);  } -void GI::SDFGI::erase() { +void GI::SDFGI::free_data() { +	// we don't free things here, we handle SDFGI differently at the moment destructing the object when it needs to change. +} + +GI::SDFGI::~SDFGI() {  	for (uint32_t i = 0; i < cascades.size(); i++) {  		const SDFGI::Cascade &c = cascades[i];  		RD::get_singleton()->free(c.light_data); @@ -1292,7 +1317,7 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) {  	push_constant.y_mult = y_mult;  	if (reads_sky && p_env.is_valid()) { -		push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); +		push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy_multiplier(p_env);  		if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_CLEAR_COLOR) {  			push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR; @@ -1609,7 +1634,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection  		Projection inv_projection = p_projections[v].inverse();  		for (int i = 0; i < 4; i++) {  			for (int j = 0; j < 3; j++) { -				push_constant.inv_projection[j][i] = inv_projection.matrix[i][j]; +				push_constant.inv_projection[j][i] = inv_projection.columns[i][j];  			}  		} @@ -1619,8 +1644,8 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection  		RD::get_singleton()->compute_list_end();  	} -	Size2 rtsize = texture_storage->render_target_get_size(p_render_target); -	copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true, false, false, false, RID(), p_view_count > 1); +	Size2i rtsize = texture_storage->render_target_get_size(p_render_target); +	copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2i(Point2i(), rtsize), true, false, false, false, RID(), p_view_count > 1);  }  void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { @@ -1773,7 +1798,8 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con  	RD::get_singleton()->draw_list_end();  } -void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data) { +	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();  	/* Update general SDFGI Buffer */  	SDFGIData sdfgi_data; @@ -1840,6 +1866,11 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r  		c.probe_world_offset[2] = probe_ofs.z;  		c.to_cell = 1.0 / cascades[i].cell_size; +		c.exposure_normalization = 1.0; +		if (p_render_data->camera_attributes.is_valid()) { +			float exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); +			c.exposure_normalization = exposure_normalization / cascades[i].baked_exposure_normalization; +		}  	}  	RD::get_singleton()->buffer_update(gi->sdfgi_ubo, 0, sizeof(SDFGIData), &sdfgi_data, RD::BARRIER_MASK_COMPUTE); @@ -1851,32 +1882,43 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r  		SDFGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS];  		uint32_t idx = 0; -		for (uint32_t j = 0; j < (uint32_t)p_scene_render->render_state.sdfgi_update_data->directional_lights->size(); j++) { +		for (uint32_t j = 0; j < (uint32_t)p_render_data->sdfgi_update_data->directional_lights->size(); j++) {  			if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {  				break;  			} -			RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j)); -			ERR_CONTINUE(!li); +			RID light_instance = p_render_data->sdfgi_update_data->directional_lights->get(j); +			ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); -			if (RSG::light_storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { +			RID light = light_storage->light_instance_get_base_light(light_instance); +			Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); + +			if (RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {  				continue;  			} -			Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); +			Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z);  			dir.y *= y_mult;  			dir.normalize();  			lights[idx].direction[0] = dir.x;  			lights[idx].direction[1] = dir.y;  			lights[idx].direction[2] = dir.z; -			Color color = RSG::light_storage->light_get_color(li->light); +			Color color = RSG::light_storage->light_get_color(light);  			color = color.srgb_to_linear();  			lights[idx].color[0] = color.r;  			lights[idx].color[1] = color.g;  			lights[idx].color[2] = color.b;  			lights[idx].type = RS::LIGHT_DIRECTIONAL; -			lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); -			lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); +			lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); +			if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { +				lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); +			} + +			if (p_render_data->camera_attributes.is_valid()) { +				lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); +			} + +			lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light);  			idx++;  		} @@ -1885,47 +1927,69 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r  		cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascade.position)) * cascade.cell_size;  		cascade_aabb.size = Vector3(1, 1, 1) * cascade_size * cascade.cell_size; -		for (uint32_t j = 0; j < p_scene_render->render_state.sdfgi_update_data->positional_light_count; j++) { +		for (uint32_t j = 0; j < p_render_data->sdfgi_update_data->positional_light_count; j++) {  			if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {  				break;  			} -			RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]); -			ERR_CONTINUE(!li); +			RID light_instance = p_render_data->sdfgi_update_data->positional_light_instances[j]; +			ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); -			uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light); +			RID light = light_storage->light_instance_get_base_light(light_instance); +			AABB light_aabb = light_storage->light_instance_get_base_aabb(light_instance); +			Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); + +			uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(light);  			if (i > max_sdfgi_cascade) {  				continue;  			} -			if (!cascade_aabb.intersects(li->aabb)) { +			if (!cascade_aabb.intersects(light_aabb)) {  				continue;  			} -			Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); +			Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z);  			//faster to not do this here  			//dir.y *= y_mult;  			//dir.normalize();  			lights[idx].direction[0] = dir.x;  			lights[idx].direction[1] = dir.y;  			lights[idx].direction[2] = dir.z; -			Vector3 pos = li->transform.origin; +			Vector3 pos = light_transform.origin;  			pos.y *= y_mult;  			lights[idx].position[0] = pos.x;  			lights[idx].position[1] = pos.y;  			lights[idx].position[2] = pos.z; -			Color color = RSG::light_storage->light_get_color(li->light); +			Color color = RSG::light_storage->light_get_color(light);  			color = color.srgb_to_linear();  			lights[idx].color[0] = color.r;  			lights[idx].color[1] = color.g;  			lights[idx].color[2] = color.b; -			lights[idx].type = RSG::light_storage->light_get_type(li->light); -			lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); -			lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); -			lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); -			lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); -			lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); -			lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); +			lights[idx].type = RSG::light_storage->light_get_type(light); + +			lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); +			if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { +				lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); + +				// Convert from Luminous Power to Luminous Intensity +				if (lights[idx].type == RS::LIGHT_OMNI) { +					lights[idx].energy *= 1.0 / (Math_PI * 4.0); +				} else if (lights[idx].type == RS::LIGHT_SPOT) { +					// Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle. +					// We make this assumption to keep them easy to control. +					lights[idx].energy *= 1.0 / Math_PI; +				} +			} + +			if (p_render_data->camera_attributes.is_valid()) { +				lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); +			} + +			lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light); +			lights[idx].attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); +			lights[idx].radius = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE); +			lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); +			lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);  			idx++;  		} @@ -1938,10 +2002,9 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r  	}  } -void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization) {  	//print_line("rendering region " + itos(p_region)); -	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); -	ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... +	ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...  	AABB bounds;  	Vector3i from;  	Vector3i size; @@ -1960,7 +2023,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr  	}  	//print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(cascades[cascade].cell_size)); -	p_scene_render->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing); +	RendererSceneRenderRD::get_singleton()->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing, p_exposure_normalization);  	if (cascade_next != cascade) {  		RD::get_singleton()->draw_command_begin_label("SDFGI Pre-Process Cascade"); @@ -1989,6 +2052,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr  		}  		cascades[cascade].all_dynamic_lights_dirty = true; +		cascades[cascade].baked_exposure_normalization = p_exposure_normalization;  		push_constant.grid_size = cascade_size;  		push_constant.cascade = cascade; @@ -2271,7 +2335,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr  		img.instantiate();  		for (uint32_t i = 0; i < cascade_size; i++) {  			Vector<uint8_t> subarr = data.slice(128 * 128 * i, 128 * 128 * (i + 1)); -			img->create(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr); +			img->set_data(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr);  			img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png");  		} @@ -2297,9 +2361,10 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr  	}  } -void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) { -	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); -	ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... +void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result) { +	ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but... + +	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();  	RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights"); @@ -2326,21 +2391,25 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co  					break;  				} -				RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_positional_light_cull_result[i][j]); -				ERR_CONTINUE(!li); +				RID light_instance = p_positional_light_cull_result[i][j]; +				ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); + +				RID light = light_storage->light_instance_get_base_light(light_instance); +				AABB light_aabb = light_storage->light_instance_get_base_aabb(light_instance); +				Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); -				uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light); +				uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(light);  				if (p_cascade_indices[i] > max_sdfgi_cascade) {  					continue;  				} -				if (!cascade_aabb.intersects(li->aabb)) { +				if (!cascade_aabb.intersects(light_aabb)) {  					continue;  				} -				lights[idx].type = RSG::light_storage->light_get_type(li->light); +				lights[idx].type = RSG::light_storage->light_get_type(light); -				Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); +				Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z);  				if (lights[idx].type == RS::LIGHT_DIRECTIONAL) {  					dir.y *= y_mult; //only makes sense for directional  					dir.normalize(); @@ -2348,22 +2417,40 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co  				lights[idx].direction[0] = dir.x;  				lights[idx].direction[1] = dir.y;  				lights[idx].direction[2] = dir.z; -				Vector3 pos = li->transform.origin; +				Vector3 pos = light_transform.origin;  				pos.y *= y_mult;  				lights[idx].position[0] = pos.x;  				lights[idx].position[1] = pos.y;  				lights[idx].position[2] = pos.z; -				Color color = RSG::light_storage->light_get_color(li->light); +				Color color = RSG::light_storage->light_get_color(light);  				color = color.srgb_to_linear();  				lights[idx].color[0] = color.r;  				lights[idx].color[1] = color.g;  				lights[idx].color[2] = color.b; -				lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); -				lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); -				lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); -				lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); -				lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); -				lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + +				lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); +				if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { +					lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); + +					// Convert from Luminous Power to Luminous Intensity +					if (lights[idx].type == RS::LIGHT_OMNI) { +						lights[idx].energy *= 1.0 / (Math_PI * 4.0); +					} else if (lights[idx].type == RS::LIGHT_SPOT) { +						// Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle. +						// We make this assumption to keep them easy to control. +						lights[idx].energy *= 1.0 / Math_PI; +					} +				} + +				if (p_render_data->camera_attributes.is_valid()) { +					lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); +				} + +				lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light); +				lights[idx].attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); +				lights[idx].radius = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE); +				lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); +				lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);  				idx++;  			} @@ -2419,7 +2506,8 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co  ////////////////////////////////////////////////////////////////////////////////  // VoxelGIInstance -void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { +	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();  	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	uint32_t data_version = gi->voxel_gi_get_data_version(probe); @@ -2761,7 +2849,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID  		last_probe_data_version = data_version;  		p_update_light_instances = true; //just in case -		p_scene_render->_base_uniforms_changed(); +		RendererSceneRenderRD::get_singleton()->base_uniforms_changed();  	}  	// UDPDATE TIME @@ -2778,13 +2866,14 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID  		{  			Transform3D to_cell = gi->voxel_gi_get_to_cell_xform(probe); -			Transform3D to_probe_xform = (transform * to_cell.affine_inverse()).affine_inverse(); +			Transform3D to_probe_xform = to_cell * transform.affine_inverse(); +  			//update lights  			for (uint32_t i = 0; i < light_count; i++) {  				VoxelGILight &l = gi->voxel_gi_lights[i];  				RID light_instance = p_light_instances[i]; -				RID light = p_scene_render->light_instance_get_base_light(light_instance); +				RID light = light_storage->light_instance_get_base_light(light_instance);  				l.type = RSG::light_storage->light_get_type(light);  				if (l.type == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { @@ -2794,16 +2883,32 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID  				l.attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);  				l.energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + +				if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { +					l.energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); + +					l.energy *= gi->voxel_gi_get_baked_exposure_normalization(probe); + +					// Convert from Luminous Power to Luminous Intensity +					if (l.type == RS::LIGHT_OMNI) { +						l.energy *= 1.0 / (Math_PI * 4.0); +					} else if (l.type == RS::LIGHT_SPOT) { +						// Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle. +						// We make this assumption to keep them easy to control. +						l.energy *= 1.0 / Math_PI; +					} +				} +  				l.radius = to_cell.basis.xform(Vector3(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();  				Color color = RSG::light_storage->light_get_color(light).srgb_to_linear();  				l.color[0] = color.r;  				l.color[1] = color.g;  				l.color[2] = color.b; -				l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); +				l.cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));  				l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); -				Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance); +				Transform3D xform = light_storage->light_instance_get_base_transform(light_instance);  				Vector3 pos = to_probe_xform.xform(xform.origin);  				Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_column(2)).normalized(); @@ -2998,12 +3103,17 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID  				Projection cm;  				cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]); -				if (p_scene_render->cull_argument.size() == 0) { -					p_scene_render->cull_argument.push_back(nullptr); +				if (RendererSceneRenderRD::get_singleton()->cull_argument.size() == 0) { +					RendererSceneRenderRD::get_singleton()->cull_argument.push_back(nullptr); +				} +				RendererSceneRenderRD::get_singleton()->cull_argument[0] = instance; + +				float exposure_normalization = 1.0; +				if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { +					exposure_normalization = gi->voxel_gi_get_baked_exposure_normalization(probe);  				} -				p_scene_render->cull_argument[0] = instance; -				p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size)); +				RendererSceneRenderRD::get_singleton()->_render_material(to_world_xform * xform, cm, true, RendererSceneRenderRD::get_singleton()->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size), exposure_normalization);  				VoxelGIDynamicPushConstant push_constant;  				memset(&push_constant, 0, sizeof(VoxelGIDynamicPushConstant)); @@ -3176,7 +3286,7 @@ void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, c  	for (int i = 0; i < 4; i++) {  		for (int j = 0; j < 4; j++) { -			push_constant.projection[i * 4 + j] = cam_transform.matrix[i][j]; +			push_constant.projection[i * 4 + j] = cam_transform.columns[i][j];  		}  	} @@ -3488,25 +3598,27 @@ void GI::free() {  	}  } -GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { -	SDFGI *sdfgi = memnew(SDFGI); +Ref<GI::SDFGI> GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { +	Ref<SDFGI> sdfgi; +	sdfgi.instantiate();  	sdfgi->create(p_env, p_world_position, p_requested_history_size, this);  	return sdfgi;  } -void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { +void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used) { +	ERR_FAIL_COND(p_render_buffers.is_null()); +  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); +	ERR_FAIL_NULL(texture_storage);  	r_voxel_gi_instances_used = 0; -	// feels a little dirty to use our container this way but.... -	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); -	ERR_FAIL_COND(rb == nullptr); - -	RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers); +	Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); +	ERR_FAIL_COND(rbgi.is_null()); +	RID voxel_gi_buffer = rbgi->get_voxel_gi_buffer();  	VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES];  	bool voxel_gi_instances_changed = false; @@ -3517,7 +3629,7 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra  	for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {  		RID texture;  		if (i < (int)p_voxel_gi_instances.size()) { -			VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]); +			VoxelGIInstance *gipi = voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]);  			if (gipi) {  				texture = gipi->texture; @@ -3555,6 +3667,11 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra  				gipd.normal_bias = voxel_gi_get_normal_bias(base_probe);  				gipd.blend_ambient = !voxel_gi_is_interior(base_probe);  				gipd.mipmaps = gipi->mipmaps.size(); +				gipd.exposure_normalization = 1.0; +				if (p_render_data->camera_attributes.is_valid()) { +					float exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); +					gipd.exposure_normalization = exposure_normalization / voxel_gi_get_baked_exposure_normalization(base_probe); +				}  			}  			r_voxel_gi_instances_used++; @@ -3564,28 +3681,30 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra  			texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);  		} -		if (texture != rb->rbgi.voxel_gi_textures[i]) { +		if (texture != rbgi->voxel_gi_textures[i]) {  			voxel_gi_instances_changed = true; -			rb->rbgi.voxel_gi_textures[i] = texture; +			rbgi->voxel_gi_textures[i] = texture;  		}  	}  	if (voxel_gi_instances_changed) {  		for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { -			if (RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { -				RD::get_singleton()->free(rb->rbgi.uniform_set[v]); +			if (RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) { +				RD::get_singleton()->free(rbgi->uniform_set[v]);  			} -			rb->rbgi.uniform_set[v] = RID(); +			rbgi->uniform_set[v] = RID();  		} -		if (rb->volumetric_fog) { -			if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { -				RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set); -				RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set); -				RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2); +		if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { +			Ref<Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); + +			if (RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) { +				RD::get_singleton()->free(fog->fog_uniform_set); +				RD::get_singleton()->free(fog->process_uniform_set); +				RD::get_singleton()->free(fog->process_uniform_set2);  			} -			rb->volumetric_fog->fog_uniform_set = RID(); -			rb->volumetric_fog->process_uniform_set = RID(); -			rb->volumetric_fog->process_uniform_set2 = RID(); +			fog->fog_uniform_set = RID(); +			fog->process_uniform_set = RID(); +			fog->process_uniform_set2 = RID();  		}  	} @@ -3598,7 +3717,14 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra  	}  } -void GI::RenderBuffersGI::free() { +RID GI::RenderBuffersGI::get_voxel_gi_buffer() { +	if (voxel_gi_buffer.is_null()) { +		voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::VoxelGIData) * GI::MAX_VOXEL_GI_INSTANCES); +	} +	return voxel_gi_buffer; +} + +void GI::RenderBuffersGI::free_data() {  	for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {  		if (RD::get_singleton()->uniform_set_is_valid(uniform_set[v])) {  			RD::get_singleton()->free(uniform_set[v]); @@ -3611,28 +3737,13 @@ void GI::RenderBuffersGI::free() {  		scene_data_ubo = RID();  	} -	if (ambient_buffer.is_valid()) { -		RD::get_singleton()->free(ambient_buffer); -		RD::get_singleton()->free(reflection_buffer); -		ambient_buffer = RID(); -		reflection_buffer = RID(); - -		// these are automatically freed when we free the textures, so just reset.. -		for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { -			ambient_slice[v] = RID(); -			reflection_slice[v] = RID(); -		} - -		view_count = 0; -	} -  	if (voxel_gi_buffer.is_valid()) {  		RD::get_singleton()->free(voxel_gi_buffer);  		voxel_gi_buffer = RID();  	}  } -void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { +void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances) {  	RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();  	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3640,65 +3751,38 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  	RD::get_singleton()->draw_command_begin_label("GI Render"); -	RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); -	ERR_FAIL_COND(rb == nullptr); +	ERR_FAIL_COND(p_render_buffers.is_null()); -	if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) { -		// Free our old buffer if applicable -		if (rb->rbgi.ambient_buffer.is_valid()) { -			RD::get_singleton()->free(rb->rbgi.ambient_buffer); -			RD::get_singleton()->free(rb->rbgi.reflection_buffer); +	Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); +	ERR_FAIL_COND(rbgi.is_null()); -			for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { -				rb->rbgi.ambient_slice[v] = RID(); -				rb->rbgi.reflection_slice[v] = RID(); -			} -		} +	Size2i internal_size = p_render_buffers->get_internal_size(); + +	if (rbgi->using_half_size_gi != half_resolution) { +		p_render_buffers->clear_context(RB_SCOPE_GI); +	} -		// Remember the view count we're using -		rb->rbgi.view_count = p_view_count; +	if (!p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) { +		Size2i size = internal_size; +		uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; -		// Create textures for our ambient and reflection data -		RD::TextureFormat tf; -		tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; -		tf.width = rb->internal_width; -		tf.height = rb->internal_height;  		if (half_resolution) { -			tf.width >>= 1; -			tf.height >>= 1; -		} -		if (p_view_count > 1) { -			tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; -			tf.array_layers = p_view_count; -		} else { -			tf.texture_type = RD::TEXTURE_TYPE_2D; -			tf.array_layers = 1; -		} -		tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; -		rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); -		RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer"); -		rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); -		RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer"); -		rb->rbgi.using_half_size_gi = half_resolution; - -		if (p_view_count == 1) { -			// Just copy, we don't need to create slices -			rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer; -			rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer; -		} else { -			for (uint32_t v = 0; v < p_view_count; v++) { -				rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0); -				rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0); -			} +			size.x >>= 1; +			size.y >>= 1;  		} + +		p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_AMBIENT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size); +		p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_REFLECTION, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size); + +		rbgi->using_half_size_gi = half_resolution;  	}  	// Setup our scene data  	{  		SceneData scene_data; -		if (rb->rbgi.scene_data_ubo.is_null()) { -			rb->rbgi.scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData)); +		if (rbgi->scene_data_ubo.is_null()) { +			rbgi->scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));  		}  		for (uint32_t v = 0; v < p_view_count; v++) { @@ -3712,10 +3796,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  		// Note that we will be ignoring the origin of this transform.  		RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform); -		scene_data.screen_size[0] = rb->internal_width; -		scene_data.screen_size[1] = rb->internal_height; +		scene_data.screen_size[0] = internal_size.x; +		scene_data.screen_size[1] = internal_size.y; -		RD::get_singleton()->buffer_update(rb->rbgi.scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); +		RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);  	}  	// Now compute the contents of our buffers. @@ -3737,22 +3821,28 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  	push_constant.z_far = p_projections[0].get_z_far();  	// these are only used if we have 1 view, else we use the projections in our scene data -	push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]); -	push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]); -	push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0]; -	push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1]; +	push_constant.proj_info[0] = -2.0f / (internal_size.x * p_projections[0].columns[0][0]); +	push_constant.proj_info[1] = -2.0f / (internal_size.y * p_projections[0].columns[1][1]); +	push_constant.proj_info[2] = (1.0f - p_projections[0].columns[0][2]) / p_projections[0].columns[0][0]; +	push_constant.proj_info[3] = (1.0f + p_projections[0].columns[1][2]) / p_projections[0].columns[1][1]; -	bool use_sdfgi = rb->sdfgi != nullptr; +	bool use_sdfgi = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI);  	bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; +	Ref<SDFGI> sdfgi; +	if (use_sdfgi) { +		sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI); +	} +  	uint32_t pipeline_specialization = 0; -	if (rb->rbgi.using_half_size_gi) { +	if (rbgi->using_half_size_gi) {  		pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES;  	}  	if (p_view_count > 1) {  		pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX;  	} -	if (p_vrs_slices[0].is_valid()) { +	bool has_vrs_texture = p_render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE); +	if (has_vrs_texture) {  		pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS;  	} @@ -3762,15 +3852,15 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  		push_constant.view_index = v;  		// setup our uniform set -		if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { +		if (rbgi->uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {  			Vector<RD::Uniform> uniforms;  			{  				RD::Uniform u;  				u.binding = 1;  				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  				for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { -					if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { -						u.append_id(rb->sdfgi->cascades[j].sdf_tex); +					if (use_sdfgi && j < sdfgi->cascades.size()) { +						u.append_id(sdfgi->cascades[j].sdf_tex);  					} else {  						u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));  					} @@ -3782,8 +3872,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				u.binding = 2;  				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  				for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { -					if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { -						u.append_id(rb->sdfgi->cascades[j].light_tex); +					if (use_sdfgi && j < sdfgi->cascades.size()) { +						u.append_id(sdfgi->cascades[j].light_tex);  					} else {  						u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));  					} @@ -3795,8 +3885,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				u.binding = 3;  				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  				for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { -					if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { -						u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); +					if (use_sdfgi && j < sdfgi->cascades.size()) { +						u.append_id(sdfgi->cascades[j].light_aniso_0_tex);  					} else {  						u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));  					} @@ -3808,8 +3898,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				u.binding = 4;  				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  				for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { -					if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { -						u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); +					if (use_sdfgi && j < sdfgi->cascades.size()) { +						u.append_id(sdfgi->cascades[j].light_aniso_1_tex);  					} else {  						u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));  					} @@ -3820,8 +3910,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  				u.binding = 5; -				if (rb->sdfgi) { -					u.append_id(rb->sdfgi->occlusion_texture); +				if (use_sdfgi) { +					u.append_id(sdfgi->occlusion_texture);  				} else {  					u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));  				} @@ -3846,7 +3936,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  				u.binding = 9; -				u.append_id(rb->rbgi.ambient_slice[v]); +				u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_AMBIENT, v, 0));  				uniforms.push_back(u);  			} @@ -3854,7 +3944,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  				u.binding = 10; -				u.append_id(rb->rbgi.reflection_slice[v]); +				u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_REFLECTION, v, 0));  				uniforms.push_back(u);  			} @@ -3862,8 +3952,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  				u.binding = 11; -				if (rb->sdfgi) { -					u.append_id(rb->sdfgi->lightprobe_texture); +				if (use_sdfgi) { +					u.append_id(sdfgi->lightprobe_texture);  				} else {  					u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));  				} @@ -3873,7 +3963,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  				u.binding = 12; -				u.append_id(rb->views[v].view_depth); +				u.append_id(p_render_buffers->get_depth_texture(v));  				uniforms.push_back(u);  			}  			{ @@ -3902,7 +3992,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;  				u.binding = 16; -				u.append_id(rb->rbgi.voxel_gi_buffer); +				u.append_id(rbgi->get_voxel_gi_buffer());  				uniforms.push_back(u);  			}  			{ @@ -3910,7 +4000,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  				u.binding = 17;  				for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { -					u.append_id(rb->rbgi.voxel_gi_textures[i]); +					u.append_id(rbgi->voxel_gi_textures[i]);  				}  				uniforms.push_back(u);  			} @@ -3918,29 +4008,29 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;  				u.binding = 18; -				u.append_id(rb->rbgi.scene_data_ubo); +				u.append_id(rbgi->scene_data_ubo);  				uniforms.push_back(u);  			}  			{  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  				u.binding = 19; -				RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS); +				RID buffer = has_vrs_texture ? p_render_buffers->get_texture_slice(RB_SCOPE_VRS, RB_TEXTURE, v, 0) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);  				u.append_id(buffer);  				uniforms.push_back(u);  			} -			rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); +			rbgi->uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);  		}  		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]); -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rbgi->uniform_set[v], 0);  		RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); -		if (rb->rbgi.using_half_size_gi) { -			RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1); +		if (rbgi->using_half_size_gi) { +			RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x >> 1, internal_size.y >> 1, 1);  		} else { -			RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1); +			RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x, internal_size.y, 1);  		}  	} @@ -3964,24 +4054,24 @@ void GI::voxel_gi_instance_free(RID p_rid) {  }  void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { -	VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); +	VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);  	ERR_FAIL_COND(!voxel_gi);  	voxel_gi->transform = p_xform;  }  bool GI::voxel_gi_needs_update(RID p_probe) const { -	VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); +	VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);  	ERR_FAIL_COND_V(!voxel_gi, false);  	return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe);  } -void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { -	VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); +void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { +	VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);  	ERR_FAIL_COND(!voxel_gi); -	voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); +	voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects);  }  void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 8860445c3b..2182ca6a20 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -44,10 +44,17 @@  #include "servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl.gen.h"  #include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h"  #include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"  #include "servers/rendering/renderer_scene_render.h"  #include "servers/rendering/rendering_device.h"  #include "servers/rendering/storage/utilities.h" +#define RB_SCOPE_GI SNAME("rbgi") +#define RB_SCOPE_SDFGI SNAME("sdfgi") + +#define RB_TEX_AMBIENT SNAME("ambient") +#define RB_TEX_REFLECTION SNAME("reflection") +  // Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound  struct RenderDataRD;  class RendererSceneRenderRD; @@ -76,6 +83,7 @@ public:  		float dynamic_range = 2.0;  		float energy = 1.0; +		float baked_exposure = 1.0;  		float bias = 1.4;  		float normal_bias = 0.0;  		float propagation = 0.5; @@ -88,6 +96,60 @@ public:  		Dependency dependency;  	}; +	/* VOXEL_GI INSTANCE */ + +	//@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself. + +	struct VoxelGIInstance { +		// access to our containers +		GI *gi = nullptr; + +		RID probe; +		RID texture; +		RID write_buffer; + +		struct Mipmap { +			RID texture; +			RID uniform_set; +			RID second_bounce_uniform_set; +			RID write_uniform_set; +			uint32_t level; +			uint32_t cell_offset; +			uint32_t cell_count; +		}; +		Vector<Mipmap> mipmaps; + +		struct DynamicMap { +			RID texture; //color normally, or emission on first pass +			RID fb_depth; //actual depth buffer for the first pass, float depth for later passes +			RID depth; //actual depth buffer for the first pass, float depth for later passes +			RID normal; //normal buffer for the first pass +			RID albedo; //emission buffer for the first pass +			RID orm; //orm buffer for the first pass +			RID fb; //used for rendering, only valid on first map +			RID uniform_set; +			uint32_t size; +			int mipmap; // mipmap to write to, -1 if no mipmap assigned +		}; + +		Vector<DynamicMap> dynamic_maps; + +		int slot = -1; +		uint32_t last_probe_version = 0; +		uint32_t last_probe_data_version = 0; + +		//uint64_t last_pass = 0; +		uint32_t render_index = 0; + +		bool has_dynamic_object_data = false; + +		Transform3D transform; + +		void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects); +		void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); +		void free_resources(); +	}; +  private:  	static GI *singleton; @@ -97,6 +159,8 @@ private:  	/* VOXEL_GI INSTANCE */ +	mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner; +  	struct VoxelGILight {  		uint32_t type;  		float energy; @@ -369,9 +433,40 @@ private:  public:  	static GI *get_singleton() { return singleton; } +	/* GI */ + +	enum { +		MAX_VOXEL_GI_INSTANCES = 8 +	}; + +	// Struct for use in render buffer +	class RenderBuffersGI : public RenderBufferCustomDataRD { +		GDCLASS(RenderBuffersGI, RenderBufferCustomDataRD) + +	private: +		RID voxel_gi_buffer; + +	public: +		RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; + +		RID full_buffer; +		RID full_dispatch; +		RID full_mask; + +		/* GI buffers */ +		bool using_half_size_gi = false; + +		RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; +		RID scene_data_ubo; + +		RID get_voxel_gi_buffer(); + +		virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; +		virtual void free_data() override; +	}; +  	/* VOXEL GI API */ -	VoxelGI *get_voxel_gi(RID p_rid) { return voxel_gi_owner.get_or_null(p_rid); };  	bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); };  	virtual RID voxel_gi_allocate() override; @@ -398,6 +493,9 @@ public:  	virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) override;  	virtual float voxel_gi_get_energy(RID p_voxel_gi) const override; +	virtual void voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) override; +	virtual float voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const override; +  	virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) override;  	virtual float voxel_gi_get_bias(RID p_voxel_gi) const override; @@ -418,72 +516,23 @@ public:  	RID voxel_gi_get_sdf_texture(RID p_voxel_gi); -	/* VOXEL_GI INSTANCE */ +	Dependency *voxel_gi_get_dependency(RID p_voxel_gi) const; -	//@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself. - -	struct VoxelGIInstance { -		// access to our containers -		GI *gi = nullptr; - -		RID probe; -		RID texture; -		RID write_buffer; - -		struct Mipmap { -			RID texture; -			RID uniform_set; -			RID second_bounce_uniform_set; -			RID write_uniform_set; -			uint32_t level; -			uint32_t cell_offset; -			uint32_t cell_count; -		}; -		Vector<Mipmap> mipmaps; - -		struct DynamicMap { -			RID texture; //color normally, or emission on first pass -			RID fb_depth; //actual depth buffer for the first pass, float depth for later passes -			RID depth; //actual depth buffer for the first pass, float depth for later passes -			RID normal; //normal buffer for the first pass -			RID albedo; //emission buffer for the first pass -			RID orm; //orm buffer for the first pass -			RID fb; //used for rendering, only valid on first map -			RID uniform_set; -			uint32_t size; -			int mipmap; // mipmap to write to, -1 if no mipmap assigned -		}; - -		Vector<DynamicMap> dynamic_maps; - -		int slot = -1; -		uint32_t last_probe_version = 0; -		uint32_t last_probe_data_version = 0; - -		//uint64_t last_pass = 0; -		uint32_t render_index = 0; - -		bool has_dynamic_object_data = false; - -		Transform3D transform; - -		void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); -		void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); -		void free_resources(); -	}; - -	mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner; - -	_FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const { -		return voxel_gi_instance_owner.get_or_null(p_probe); -	}; +	/* VOXEL_GI INSTANCE */  	_FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) { -		VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); +		VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);  		ERR_FAIL_COND_V(!voxel_gi, RID());  		return voxel_gi->texture;  	}; +	_FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) { +		VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); +		ERR_FAIL_NULL(voxel_gi); + +		voxel_gi->render_index = p_index; +	}; +  	bool voxel_gi_instance_owns(RID p_rid) const {  		return voxel_gi_instance_owner.owns(p_rid);  	} @@ -494,7 +543,10 @@ public:  	/* SDFGI */ -	struct SDFGI { +	class SDFGI : public RenderBufferCustomDataRD { +		GDCLASS(SDFGI, RenderBufferCustomDataRD) + +	public:  		enum {  			MAX_CASCADES = 8,  			CASCADE_SIZE = 128, @@ -512,6 +564,7 @@ public:  				float to_cell;  				int32_t probe_offset[3];  				uint32_t pad; +				float pad2[4];  			};  			//cascade blocks are full-size for volume (128^3), half size for albedo/emission @@ -551,6 +604,8 @@ public:  			RID integrate_uniform_set;  			RID lights_buffer; +			float baked_exposure_normalization = 1.0; +  			bool all_dynamic_lights_dirty = true;  		}; @@ -617,8 +672,11 @@ public:  		int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically  		RID integrate_sky_uniform_set; +		virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; +		virtual void free_data() override; +		~SDFGI(); +  		void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi); -		void erase();  		void update(RID p_env, const Vector3 &p_world_position);  		void update_light();  		void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky); @@ -629,9 +687,9 @@ public:  		void debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views);  		void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); -		void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render); -		void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render); -		void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render); +		void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data); +		void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization); +		void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);  	};  	RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16; @@ -648,34 +706,6 @@ public:  	int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; } -	/* GI */ -	enum { -		MAX_VOXEL_GI_INSTANCES = 8 -	}; - -	// Struct for use in render buffer -	struct RenderBuffersGI { -		RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; -		RID voxel_gi_buffer; - -		RID full_buffer; -		RID full_dispatch; -		RID full_mask; - -		/* GI buffers */ -		RID ambient_buffer; -		RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS]; -		RID reflection_buffer; -		RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS]; -		bool using_half_size_gi = false; -		uint32_t view_count = 1; - -		RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; -		RID scene_data_ubo; - -		void free(); -	}; -  	struct SDFGIData {  		float grid_size[3];  		uint32_t max_cascades; @@ -705,6 +735,8 @@ public:  			float to_probe; // 1/bounds * grid_size  			int32_t probe_world_offset[3];  			float to_cell; // 1/bounds * grid_size +			float pad[3]; +			float exposure_normalization;  		};  		ProbeCascadeData cascades[SDFGI::MAX_CASCADES]; @@ -720,6 +752,9 @@ public:  		float normal_bias; // 4 - 88  		uint32_t blend_ambient; // 4 - 92  		uint32_t mipmaps; // 4 - 96 + +		float pad[3]; // 12 - 108 +		float exposure_normalization; // 4 - 112  	};  	struct SceneData { @@ -775,15 +810,15 @@ public:  	void init(RendererRD::SkyRD *p_sky);  	void free(); -	SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); +	Ref<SDFGI> create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); -	void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render); -	void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); +	void setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used); +	void process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances);  	RID voxel_gi_instance_create(RID p_base);  	void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);  	bool voxel_gi_needs_update(RID p_probe) const; -	void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); +	void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects);  	void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);  }; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 6433a39863..0acd48c22a 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -35,6 +35,7 @@  #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"  #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"  #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"  #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"  #include "servers/rendering/rendering_server_default.h"  #include "servers/rendering/rendering_server_globals.h" @@ -114,12 +115,16 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) {  	for (int i = 0; i < gen_code.defines.size(); i++) {  		print_line(gen_code.defines[i]);  	} + +	HashMap<String, String>::Iterator el = gen_code.code.begin(); +	while (el) { +		print_line("\n**code " + el->key + ":\n" + el->value); +		++el; +	} +  	print_line("\n**uniforms:\n" + gen_code.uniforms); -	//	print_line("\n**vertex_globals:\n" + gen_code.vertex_global); -	//	print_line("\n**vertex_code:\n" + gen_code.vertex); -	print_line("\n**fragment_globals:\n" + gen_code.fragment_global); -	print_line("\n**fragment_code:\n" + gen_code.fragment); -	print_line("\n**light_code:\n" + gen_code.light); +	print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]); +	print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);  #endif  	scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines); @@ -147,7 +152,7 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) {  	valid = true;  } -void SkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void SkyRD::SkyShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {  	if (!p_texture.is_valid()) {  		if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {  			default_texture_params[p_name].erase(p_index); @@ -215,7 +220,7 @@ void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage:  	}  } -bool SkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const { +bool SkyRD::SkyShaderData::is_parameter_texture(const StringName &p_param) const {  	if (!uniforms.has(p_param)) {  		return false;  	} @@ -263,7 +268,7 @@ bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant  	uniform_set_updated = true; -	return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); +	return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL, true);  }  SkyRD::SkyMaterialData::~SkyMaterialData() { @@ -288,22 +293,21 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar  	p_array[11] = 0;  } -void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) { +void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) {  	SkyPushConstant sky_push_constant;  	memset(&sky_push_constant, 0, sizeof(SkyPushConstant));  	for (uint32_t v = 0; v < p_view_count; v++) {  		// We only need key components of our projection matrix -		sky_push_constant.projections[v][0] = p_projections[v].matrix[2][0]; -		sky_push_constant.projections[v][1] = p_projections[v].matrix[0][0]; -		sky_push_constant.projections[v][2] = p_projections[v].matrix[2][1]; -		sky_push_constant.projections[v][3] = p_projections[v].matrix[1][1]; +		sky_push_constant.projections[v][0] = p_projections[v].columns[2][0]; +		sky_push_constant.projections[v][1] = p_projections[v].columns[0][0]; +		sky_push_constant.projections[v][2] = p_projections[v].columns[2][1]; +		sky_push_constant.projections[v][3] = p_projections[v].columns[1][1];  	}  	sky_push_constant.position[0] = p_position.x;  	sky_push_constant.position[1] = p_position.y;  	sky_push_constant.position[2] = p_position.z; -	sky_push_constant.multiplier = p_multiplier;  	sky_push_constant.time = p_time;  	sky_push_constant.luminance_multiplier = p_luminance_multiplier;  	store_transform_3x3(p_orientation, sky_push_constant.orientation); @@ -357,7 +361,7 @@ void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bo  	uint32_t w = p_size, h = p_size;  	EffectsRD *effects = RendererCompositorRD::singleton->get_effects(); -	ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised"); +	ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialized");  	bool prefer_raster_effects = effects->get_prefer_raster_effects();  	if (p_use_array) { @@ -461,7 +465,7 @@ void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bo  void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) {  	RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); -	ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); +	ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized");  	bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();  	if (prefer_raster_effects) { @@ -519,7 +523,7 @@ void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) {  void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {  	RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); -	ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); +	ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized");  	bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();  	if (prefer_raster_effects) { @@ -588,7 +592,7 @@ void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_array  void SkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) {  	RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); -	ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); +	ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized");  	bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();  	RD::get_singleton()->draw_command_begin_label("Update Radiance Cubemap Array Mipmaps"); @@ -758,7 +762,7 @@ Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, con  		RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();  		RD::TextureFormat tf; -		tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; +		tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; // Could be RGBA16  		tf.width = p_size.width;  		tf.height = p_size.height;  		tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; @@ -768,9 +772,7 @@ Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, con  		Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0);  		RD::get_singleton()->free(rad_tex); -		Ref<Image> img; -		img.instantiate(); -		img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data); +		Ref<Image> img = Image::create_from_data(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data);  		for (int i = 0; i < p_size.width; i++) {  			for (int j = 0; j < p_size.height; j++) {  				Color c = img->get_pixel(i, j); @@ -864,7 +866,7 @@ void SkyRD::init() {  		actions.renames["COLOR"] = "color";  		actions.renames["ALPHA"] = "alpha";  		actions.renames["EYEDIR"] = "cube_normal"; -		actions.renames["POSITION"] = "params.position_multiplier.xyz"; +		actions.renames["POSITION"] = "params.position";  		actions.renames["SKY_COORDS"] = "panorama_coords";  		actions.renames["SCREEN_UV"] = "uv";  		actions.renames["FRAGCOORD"] = "gl_FragCoord"; @@ -903,6 +905,7 @@ void SkyRD::init() {  		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; @@ -1106,7 +1109,7 @@ SkyRD::~SkyRD() {  	RD::get_singleton()->free(index_buffer); //array gets freed as dependency  } -void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {  	RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();  	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	ERR_FAIL_COND(p_env.is_null()); @@ -1195,18 +1198,17 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh  			// 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) { +				if (!light_storage->owns_light_instance(p_lights[i])) {  					continue;  				} -				RID base = li->light; +				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 = li->transform; +					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; @@ -1216,6 +1218,14 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh  					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; @@ -1228,7 +1238,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh  						// 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)); +						angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter));  					} else {  						angular_diameter = 0.0;  					} @@ -1248,6 +1258,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh  				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;  				}  			} @@ -1283,24 +1294,25 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh  	//setup fog variables  	sky_scene_state.ubo.volumetric_fog_enabled = false;  	if (p_render_buffers.is_valid()) { -		if (p_scene_render->render_buffers_has_volumetric_fog(p_render_buffers)) { +		if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { +			Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);  			sky_scene_state.ubo.volumetric_fog_enabled = true; -			float fog_end = p_scene_render->render_buffers_get_volumetric_fog_end(p_render_buffers); +			float fog_end = fog->length;  			if (fog_end > 0.0) {  				sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;  			} else {  				sky_scene_state.ubo.volumetric_fog_inv_length = 1.0;  			} -			float fog_detail_spread = p_scene_render->render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //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 {  				sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;  			} -			sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers); +			sky_scene_state.fog_uniform_set = fog->sky_uniform_set;  		}  	} @@ -1315,6 +1327,9 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh  	sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;  	sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_env); +	sky_scene_state.ubo.fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_fog_sky_affect(p_env); +	sky_scene_state.ubo.volumetric_fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_sky_affect(p_env); +  	RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);  } @@ -1347,8 +1362,6 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D  	ERR_FAIL_COND(!shader_data); -	float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); -  	bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY;  	RS::SkyMode sky_mode = sky->mode; @@ -1411,7 +1424,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D  				RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);  				cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); -				_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); +				_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);  				RD::get_singleton()->draw_list_end();  			}  			RD::get_singleton()->draw_command_end_label(); @@ -1430,7 +1443,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D  				RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);  				cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); -				_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); +				_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);  				RD::get_singleton()->draw_list_end();  			}  			RD::get_singleton()->draw_command_end_label(); @@ -1445,7 +1458,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D  			RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);  			cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); -			_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); +			_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);  			RD::get_singleton()->draw_list_end();  		}  		RD::get_singleton()->draw_command_end_label(); @@ -1471,7 +1484,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D  			}  			sky->processing_layer = 1;  		} - +		sky->baked_exposure = p_luminance_multiplier;  		sky->reflection.dirty = false;  	} else { @@ -1487,7 +1500,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D  	}  } -void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time) { +void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {  	RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();  	ERR_FAIL_COND(p_env.is_null()); @@ -1532,7 +1545,6 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth  	Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);  	sky_transform.invert(); -	float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);  	float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);  	// Camera @@ -1563,7 +1575,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth  		clear_colors.push_back(Color(0.0, 0.0, 0.0));  		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); -		_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); +		_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);  		RD::get_singleton()->draw_list_end();  	} @@ -1576,7 +1588,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth  		clear_colors.push_back(Color(0.0, 0.0, 0.0));  		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); -		_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); +		_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);  		RD::get_singleton()->draw_list_end();  	} @@ -1590,7 +1602,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth  	}  	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); -	_render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); +	_render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);  	RD::get_singleton()->draw_list_end();  } @@ -1630,7 +1642,6 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio  	Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);  	sky_transform.invert(); -	float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);  	float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);  	// Camera @@ -1661,7 +1672,7 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio  		clear_colors.push_back(Color(0.0, 0.0, 0.0));  		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); -		_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); +		_render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);  		RD::get_singleton()->draw_list_end();  	} @@ -1674,7 +1685,7 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio  		clear_colors.push_back(Color(0.0, 0.0, 0.0));  		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); -		_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); +		_render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);  		RD::get_singleton()->draw_list_end();  	}  } @@ -1724,7 +1735,6 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie  	Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);  	sky_transform.invert(); -	float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env);  	float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);  	// Camera @@ -1755,7 +1765,7 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie  		texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;  	} -	_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); +	_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);  }  void SkyRD::invalidate_sky(Sky *p_sky) { @@ -1877,6 +1887,13 @@ RID SkyRD::sky_get_material(RID p_sky) const {  	return sky->material;  } +float SkyRD::sky_get_baked_exposure(RID p_sky) const { +	Sky *sky = get_sky(p_sky); +	ERR_FAIL_COND_V(!sky, 1.0); + +	return sky->baked_exposure; +} +  RID SkyRD::allocate_sky_rid() {  	return sky_owner.allocate_rid();  } diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h index 080165c112..45c4f9bda7 100644 --- a/servers/rendering/renderer_rd/environment/sky.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -42,6 +42,7 @@  // Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound  class RendererSceneRenderRD; +class RenderSceneBuffersRD;  namespace RendererRD { @@ -100,10 +101,9 @@ private:  		float orientation[12]; // 48 - 48  		float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 80  		float position[3]; // 12 - 92 -		float multiplier; // 4 - 96 -		float time; // 4 - 100 -		float luminance_multiplier; // 4 - 104 -		float pad[2]; // 8 - 112 // Using pad to align on 16 bytes +		float time; // 4 - 96 +		float pad[3]; // 12 - 108 +		float luminance_multiplier; // 4 - 112  		// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.  	}; @@ -130,10 +130,10 @@ private:  		virtual void set_code(const String &p_Code);  		virtual void set_path_hint(const String &p_hint); -		virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); +		virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);  		virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;  		virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; -		virtual bool is_param_texture(const StringName &p_param) const; +		virtual bool is_parameter_texture(const StringName &p_param) const;  		virtual bool is_animated() const;  		virtual bool casts_shadows() const;  		virtual Variant get_default_parameter(const StringName &p_parameter) const; @@ -143,25 +143,28 @@ private:  		virtual ~SkyShaderData();  	}; -	void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier); +	void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier);  public:  	struct SkySceneState {  		struct UBO { -			uint32_t volumetric_fog_enabled; -			float volumetric_fog_inv_length; -			float volumetric_fog_detail_spread; - -			float fog_aerial_perspective; - -			float fog_light_color[3]; -			float fog_sun_scatter; - -			uint32_t fog_enabled; -			float fog_density; - -			float z_far; -			uint32_t directional_light_count; +			uint32_t volumetric_fog_enabled; // 4 - 4 +			float volumetric_fog_inv_length; // 4 - 8 +			float volumetric_fog_detail_spread; // 4 - 12 +			float volumetric_fog_sky_affect; // 4 - 16 + +			uint32_t fog_enabled; // 4 - 20 +			float fog_sky_affect; // 4 - 24 +			float fog_density; // 4 - 28 +			float fog_sun_scatter; // 4 - 32 + +			float fog_light_color[3]; // 12 - 44 +			float fog_aerial_perspective; // 4 - 48 + +			float z_far; // 4 - 52 +			uint32_t directional_light_count; // 4 - 56 +			uint32_t pad1; // 4 - 60 +			uint32_t pad2; // 4 - 64  		};  		UBO ubo; @@ -264,6 +267,7 @@ public:  		bool dirty = false;  		int processing_layer = 0;  		Sky *dirty_list = nullptr; +		float baked_exposure = 1.0;  		//State to track when radiance cubemap needs updating  		SkyMaterialData *prev_material = nullptr; @@ -296,9 +300,9 @@ public:  	void set_texture_format(RD::DataFormat p_texture_format);  	~SkyRD(); -	void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); +	void setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);  	void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); -	void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer +	void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); // only called by clustered renderer  	void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);  	void draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); @@ -306,6 +310,8 @@ public:  	void update_dirty_skys();  	RID sky_get_material(RID p_sky) const; +	RID sky_get_radiance_texture_rd(RID p_sky) const; +	float sky_get_baked_exposure(RID p_sky) const;  	RID allocate_sky_rid();  	void initialize_sky_rid(RID p_rid); @@ -315,8 +321,6 @@ public:  	void sky_set_mode(RID p_sky, RS::SkyMode p_mode);  	void sky_set_material(RID p_sky, RID p_material);  	Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size); - -	RID sky_get_radiance_texture_rd(RID p_sky) const;  };  } // namespace RendererRD |