1 | /**************************************************************************/ |
2 | /* fog.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "fog.h" |
32 | |
33 | #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" |
34 | #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" |
35 | #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" |
36 | #include "servers/rendering/rendering_server_default.h" |
37 | |
38 | using namespace RendererRD; |
39 | |
40 | Fog *Fog::singleton = nullptr; |
41 | |
42 | Fog::Fog() { |
43 | singleton = this; |
44 | } |
45 | |
46 | Fog::~Fog() { |
47 | singleton = nullptr; |
48 | } |
49 | |
50 | /* FOG VOLUMES */ |
51 | |
52 | RID Fog::fog_volume_allocate() { |
53 | return fog_volume_owner.allocate_rid(); |
54 | } |
55 | |
56 | void Fog::fog_volume_initialize(RID p_rid) { |
57 | fog_volume_owner.initialize_rid(p_rid, FogVolume()); |
58 | } |
59 | |
60 | void Fog::fog_volume_free(RID p_rid) { |
61 | FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid); |
62 | fog_volume->dependency.deleted_notify(p_rid); |
63 | fog_volume_owner.free(p_rid); |
64 | } |
65 | |
66 | Dependency *Fog::fog_volume_get_dependency(RID p_fog_volume) const { |
67 | FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); |
68 | ERR_FAIL_NULL_V(fog_volume, nullptr); |
69 | |
70 | return &fog_volume->dependency; |
71 | } |
72 | |
73 | void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { |
74 | FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); |
75 | ERR_FAIL_COND(!fog_volume); |
76 | |
77 | if (p_shape == fog_volume->shape) { |
78 | return; |
79 | } |
80 | |
81 | fog_volume->shape = p_shape; |
82 | fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); |
83 | } |
84 | |
85 | void Fog::fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) { |
86 | FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); |
87 | ERR_FAIL_COND(!fog_volume); |
88 | |
89 | fog_volume->size = p_size; |
90 | fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); |
91 | } |
92 | |
93 | void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) { |
94 | FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); |
95 | ERR_FAIL_COND(!fog_volume); |
96 | fog_volume->material = p_material; |
97 | } |
98 | |
99 | RID Fog::fog_volume_get_material(RID p_fog_volume) const { |
100 | FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); |
101 | ERR_FAIL_COND_V(!fog_volume, RID()); |
102 | |
103 | return fog_volume->material; |
104 | } |
105 | |
106 | RS::FogVolumeShape Fog::fog_volume_get_shape(RID p_fog_volume) const { |
107 | FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); |
108 | ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX); |
109 | |
110 | return fog_volume->shape; |
111 | } |
112 | |
113 | AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { |
114 | FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); |
115 | ERR_FAIL_COND_V(!fog_volume, AABB()); |
116 | |
117 | switch (fog_volume->shape) { |
118 | case RS::FOG_VOLUME_SHAPE_ELLIPSOID: |
119 | case RS::FOG_VOLUME_SHAPE_CONE: |
120 | case RS::FOG_VOLUME_SHAPE_CYLINDER: |
121 | case RS::FOG_VOLUME_SHAPE_BOX: { |
122 | AABB aabb; |
123 | aabb.position = -fog_volume->size / 2; |
124 | aabb.size = fog_volume->size; |
125 | return aabb; |
126 | } |
127 | default: { |
128 | // Need some size otherwise will get culled |
129 | return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); |
130 | } |
131 | } |
132 | } |
133 | |
134 | Vector3 Fog::fog_volume_get_size(RID p_fog_volume) const { |
135 | const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); |
136 | ERR_FAIL_COND_V(!fog_volume, Vector3()); |
137 | return fog_volume->size; |
138 | } |
139 | |
140 | //////////////////////////////////////////////////////////////////////////////// |
141 | // Fog material |
142 | |
143 | bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { |
144 | uniform_set_updated = true; |
145 | |
146 | 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, true); |
147 | } |
148 | |
149 | Fog::FogMaterialData::~FogMaterialData() { |
150 | free_parameters_uniform_set(uniform_set); |
151 | } |
152 | |
153 | RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() { |
154 | FogShaderData *shader_data = memnew(FogShaderData); |
155 | return shader_data; |
156 | } |
157 | |
158 | RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() { |
159 | return Fog::get_singleton()->_create_fog_shader_func(); |
160 | }; |
161 | |
162 | RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { |
163 | FogMaterialData *material_data = memnew(FogMaterialData); |
164 | material_data->shader_data = p_shader; |
165 | //update will happen later anyway so do nothing. |
166 | return material_data; |
167 | } |
168 | |
169 | RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { |
170 | return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); |
171 | }; |
172 | |
173 | //////////////////////////////////////////////////////////////////////////////// |
174 | // FOG VOLUMES INSTANCE |
175 | |
176 | RID Fog::fog_volume_instance_create(RID p_fog_volume) { |
177 | FogVolumeInstance fvi; |
178 | fvi.volume = p_fog_volume; |
179 | return fog_volume_instance_owner.make_rid(fvi); |
180 | } |
181 | |
182 | void Fog::fog_instance_free(RID p_rid) { |
183 | fog_volume_instance_owner.free(p_rid); |
184 | } |
185 | |
186 | //////////////////////////////////////////////////////////////////////////////// |
187 | // Volumetric Fog Shader |
188 | |
189 | void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array) { |
190 | MaterialStorage *material_storage = MaterialStorage::get_singleton(); |
191 | |
192 | { |
193 | String defines = "#define SAMPLERS_BINDING_FIRST_INDEX " + itos(SAMPLERS_BINDING_FIRST_INDEX) + "\n" ; |
194 | // Initialize local fog shader |
195 | Vector<String> volumetric_fog_modes; |
196 | volumetric_fog_modes.push_back("" ); |
197 | volumetric_fog.shader.initialize(volumetric_fog_modes, defines); |
198 | |
199 | material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs); |
200 | material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_material_funcs); |
201 | volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); |
202 | } |
203 | |
204 | { |
205 | ShaderCompiler::DefaultIdentifierActions actions; |
206 | |
207 | actions.renames["TIME" ] = "scene_params.time" ; |
208 | actions.renames["PI" ] = _MKSTR(Math_PI); |
209 | actions.renames["TAU" ] = _MKSTR(Math_TAU); |
210 | actions.renames["E" ] = _MKSTR(Math_E); |
211 | actions.renames["WORLD_POSITION" ] = "world.xyz" ; |
212 | actions.renames["OBJECT_POSITION" ] = "params.position" ; |
213 | actions.renames["UVW" ] = "uvw" ; |
214 | actions.renames["SIZE" ] = "params.size" ; |
215 | actions.renames["ALBEDO" ] = "albedo" ; |
216 | actions.renames["DENSITY" ] = "density" ; |
217 | actions.renames["EMISSION" ] = "emission" ; |
218 | actions.renames["SDF" ] = "sdf" ; |
219 | |
220 | actions.usage_defines["SDF" ] = "#define SDF_USED\n" ; |
221 | actions.usage_defines["DENSITY" ] = "#define DENSITY_USED\n" ; |
222 | actions.usage_defines["ALBEDO" ] = "#define ALBEDO_USED\n" ; |
223 | actions.usage_defines["EMISSION" ] = "#define EMISSION_USED\n" ; |
224 | |
225 | actions.base_texture_binding_index = 1; |
226 | actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL; |
227 | actions.base_uniform_string = "material." ; |
228 | |
229 | actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; |
230 | actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; |
231 | actions.global_buffer_array_variable = "global_variables.data" ; |
232 | |
233 | volumetric_fog.compiler.initialize(actions); |
234 | } |
235 | |
236 | { |
237 | // default material and shader for fog shader |
238 | volumetric_fog.default_shader = material_storage->shader_allocate(); |
239 | material_storage->shader_initialize(volumetric_fog.default_shader); |
240 | material_storage->shader_set_code(volumetric_fog.default_shader, R"( |
241 | // Default fog shader. |
242 | |
243 | shader_type fog; |
244 | |
245 | void fog() { |
246 | DENSITY = 1.0; |
247 | ALBEDO = vec3(1.0); |
248 | } |
249 | )" ); |
250 | volumetric_fog.default_material = material_storage->material_allocate(); |
251 | material_storage->material_initialize(volumetric_fog.default_material); |
252 | material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); |
253 | |
254 | FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); |
255 | volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); |
256 | |
257 | Vector<RD::Uniform> uniforms; |
258 | |
259 | { |
260 | RD::Uniform u; |
261 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
262 | u.binding = 2; |
263 | u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer()); |
264 | uniforms.push_back(u); |
265 | } |
266 | |
267 | uniforms.append_array(material_storage->get_default_sampler_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); |
268 | |
269 | volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE); |
270 | } |
271 | |
272 | { |
273 | String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(p_max_directional_lights) + "\n" ; |
274 | defines += "\n#define MAX_SKY_LOD " + itos(p_roughness_layers - 1) + ".0\n" ; |
275 | if (p_is_using_radiance_cubemap_array) { |
276 | defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n" ; |
277 | } |
278 | Vector<String> volumetric_fog_modes; |
279 | volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n" ); |
280 | volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n" ); |
281 | volumetric_fog_modes.push_back("\n#define MODE_FILTER\n" ); |
282 | volumetric_fog_modes.push_back("\n#define MODE_FOG\n" ); |
283 | volumetric_fog_modes.push_back("\n#define MODE_COPY\n" ); |
284 | |
285 | volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines); |
286 | volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create(); |
287 | for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) { |
288 | volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i)); |
289 | } |
290 | volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO)); |
291 | } |
292 | } |
293 | |
294 | void Fog::free_fog_shader() { |
295 | MaterialStorage *material_storage = MaterialStorage::get_singleton(); |
296 | |
297 | if (volumetric_fog.process_shader_version.is_valid()) { |
298 | volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version); |
299 | } |
300 | if (volumetric_fog.volume_ubo.is_valid()) { |
301 | RD::get_singleton()->free(volumetric_fog.volume_ubo); |
302 | } |
303 | if (volumetric_fog.params_ubo.is_valid()) { |
304 | RD::get_singleton()->free(volumetric_fog.params_ubo); |
305 | } |
306 | if (volumetric_fog.default_shader.is_valid()) { |
307 | material_storage->shader_free(volumetric_fog.default_shader); |
308 | } |
309 | if (volumetric_fog.default_material.is_valid()) { |
310 | material_storage->material_free(volumetric_fog.default_material); |
311 | } |
312 | } |
313 | |
314 | void Fog::FogShaderData::set_code(const String &p_code) { |
315 | //compile |
316 | |
317 | code = p_code; |
318 | valid = false; |
319 | ubo_size = 0; |
320 | uniforms.clear(); |
321 | |
322 | if (code.is_empty()) { |
323 | return; //just invalid, but no error |
324 | } |
325 | |
326 | ShaderCompiler::GeneratedCode gen_code; |
327 | ShaderCompiler::IdentifierActions actions; |
328 | actions.entry_point_stages["fog" ] = ShaderCompiler::STAGE_COMPUTE; |
329 | |
330 | uses_time = false; |
331 | |
332 | actions.usage_flag_pointers["TIME" ] = &uses_time; |
333 | |
334 | actions.uniforms = &uniforms; |
335 | |
336 | Fog *fog_singleton = Fog::get_singleton(); |
337 | |
338 | Error err = fog_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code); |
339 | ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed." ); |
340 | |
341 | if (version.is_null()) { |
342 | version = fog_singleton->volumetric_fog.shader.version_create(); |
343 | } |
344 | |
345 | fog_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines); |
346 | ERR_FAIL_COND(!fog_singleton->volumetric_fog.shader.version_is_valid(version)); |
347 | |
348 | ubo_size = gen_code.uniform_total_size; |
349 | ubo_offsets = gen_code.uniform_offsets; |
350 | texture_uniforms = gen_code.texture_uniforms; |
351 | |
352 | pipeline = RD::get_singleton()->compute_pipeline_create(fog_singleton->volumetric_fog.shader.version_get_shader(version, 0)); |
353 | |
354 | valid = true; |
355 | } |
356 | |
357 | bool Fog::FogShaderData::is_animated() const { |
358 | return false; |
359 | } |
360 | |
361 | bool Fog::FogShaderData::casts_shadows() const { |
362 | return false; |
363 | } |
364 | |
365 | RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const { |
366 | Fog *fog_singleton = Fog::get_singleton(); |
367 | |
368 | return fog_singleton->volumetric_fog.shader.version_get_native_source_code(version); |
369 | } |
370 | |
371 | Fog::FogShaderData::~FogShaderData() { |
372 | Fog *fog_singleton = Fog::get_singleton(); |
373 | ERR_FAIL_COND(!fog_singleton); |
374 | //pipeline variants will clear themselves if shader is gone |
375 | if (version.is_valid()) { |
376 | fog_singleton->volumetric_fog.shader.version_free(version); |
377 | } |
378 | } |
379 | |
380 | //////////////////////////////////////////////////////////////////////////////// |
381 | // Volumetric Fog |
382 | |
383 | bool Fog::VolumetricFog::sync_gi_dependent_sets_validity(bool p_ensure_freed) { |
384 | bool null = gi_dependent_sets.process_uniform_set_density.is_null(); |
385 | bool valid = !null && RD::get_singleton()->uniform_set_is_valid(gi_dependent_sets.process_uniform_set_density); |
386 | |
387 | #ifdef DEV_ENABLED |
388 | // It's all-or-nothing, or something else has changed that requires dev attention. |
389 | DEV_ASSERT(null == gi_dependent_sets.process_uniform_set.is_null()); |
390 | DEV_ASSERT(null == gi_dependent_sets.process_uniform_set2.is_null()); |
391 | DEV_ASSERT(valid == RD::get_singleton()->uniform_set_is_valid(gi_dependent_sets.process_uniform_set)); |
392 | DEV_ASSERT(valid == RD::get_singleton()->uniform_set_is_valid(gi_dependent_sets.process_uniform_set2)); |
393 | #endif |
394 | |
395 | if (valid) { |
396 | if (p_ensure_freed) { |
397 | RD::get_singleton()->free(gi_dependent_sets.process_uniform_set_density); |
398 | RD::get_singleton()->free(gi_dependent_sets.process_uniform_set); |
399 | RD::get_singleton()->free(gi_dependent_sets.process_uniform_set2); |
400 | valid = false; |
401 | } |
402 | } |
403 | |
404 | if (!valid && !null) { |
405 | gi_dependent_sets = {}; |
406 | } |
407 | |
408 | return valid; |
409 | } |
410 | |
411 | void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) { |
412 | width = fog_size.x; |
413 | height = fog_size.y; |
414 | depth = fog_size.z; |
415 | |
416 | RD::TextureFormat tf; |
417 | tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; |
418 | tf.width = fog_size.x; |
419 | tf.height = fog_size.y; |
420 | tf.depth = fog_size.z; |
421 | tf.texture_type = RD::TEXTURE_TYPE_3D; |
422 | tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; |
423 | |
424 | light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); |
425 | RD::get_singleton()->set_resource_name(light_density_map, "Fog light-density map" ); |
426 | |
427 | tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; |
428 | |
429 | prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); |
430 | RD::get_singleton()->set_resource_name(prev_light_density_map, "Fog previous light-density map" ); |
431 | RD::get_singleton()->texture_clear(prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); |
432 | |
433 | tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; |
434 | |
435 | fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); |
436 | RD::get_singleton()->set_resource_name(fog_map, "Fog map" ); |
437 | |
438 | #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) |
439 | Vector<uint8_t> dm; |
440 | dm.resize(fog_size.x * fog_size.y * fog_size.z * 4); |
441 | dm.fill(0); |
442 | |
443 | density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); |
444 | RD::get_singleton()->set_resource_name(density_map, "Fog density map" ); |
445 | light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); |
446 | RD::get_singleton()->set_resource_name(light_map, "Fog light map" ); |
447 | emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm); |
448 | RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map" ); |
449 | #else |
450 | tf.format = RD::DATA_FORMAT_R32_UINT; |
451 | tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; |
452 | density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); |
453 | RD::get_singleton()->set_resource_name(density_map, "Fog density map" ); |
454 | RD::get_singleton()->texture_clear(density_map, Color(0, 0, 0, 0), 0, 1, 0, 1); |
455 | light_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); |
456 | RD::get_singleton()->set_resource_name(light_map, "Fog light map" ); |
457 | RD::get_singleton()->texture_clear(light_map, Color(0, 0, 0, 0), 0, 1, 0, 1); |
458 | emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); |
459 | RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map" ); |
460 | RD::get_singleton()->texture_clear(emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1); |
461 | #endif |
462 | |
463 | Vector<RD::Uniform> uniforms; |
464 | { |
465 | RD::Uniform u; |
466 | u.binding = 0; |
467 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
468 | u.append_id(fog_map); |
469 | uniforms.push_back(u); |
470 | } |
471 | |
472 | sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_sky_shader, RendererRD::SkyRD::SKY_SET_FOG); |
473 | } |
474 | |
475 | Fog::VolumetricFog::~VolumetricFog() { |
476 | RD::get_singleton()->free(prev_light_density_map); |
477 | RD::get_singleton()->free(light_density_map); |
478 | RD::get_singleton()->free(fog_map); |
479 | RD::get_singleton()->free(density_map); |
480 | RD::get_singleton()->free(light_map); |
481 | RD::get_singleton()->free(emissive_map); |
482 | |
483 | if (fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(fog_uniform_set)) { |
484 | RD::get_singleton()->free(fog_uniform_set); |
485 | } |
486 | if (copy_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(copy_uniform_set)) { |
487 | RD::get_singleton()->free(copy_uniform_set); |
488 | } |
489 | |
490 | sync_gi_dependent_sets_validity(true); |
491 | |
492 | if (sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_uniform_set)) { |
493 | RD::get_singleton()->free(sdfgi_uniform_set); |
494 | } |
495 | if (sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_uniform_set)) { |
496 | RD::get_singleton()->free(sky_uniform_set); |
497 | } |
498 | } |
499 | |
500 | Vector3i Fog::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) { |
501 | Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point); |
502 | view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera |
503 | Vector3 fog_position = Vector3(0, 0, 0); |
504 | |
505 | view_position.y = -view_position.y; |
506 | fog_position.z = -view_position.z / fog_end; |
507 | fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5; |
508 | fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5; |
509 | fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread)); |
510 | fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5); |
511 | |
512 | fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x); |
513 | fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y); |
514 | fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z); |
515 | |
516 | return Vector3i(fog_position); |
517 | } |
518 | |
519 | void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { |
520 | RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); |
521 | RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); |
522 | |
523 | RENDER_TIMESTAMP("> Volumetric Fog" ); |
524 | RD::get_singleton()->draw_command_begin_label("Volumetric Fog" ); |
525 | |
526 | Ref<VolumetricFog> fog = p_settings.vfog; |
527 | |
528 | if (p_fog_volumes.size() > 0) { |
529 | RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes" ); |
530 | |
531 | RENDER_TIMESTAMP("Render FogVolumes" ); |
532 | |
533 | VolumetricFogShader::VolumeUBO params; |
534 | |
535 | Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); |
536 | Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); |
537 | float z_near = p_cam_projection.get_z_near(); |
538 | float z_far = p_cam_projection.get_z_far(); |
539 | float fog_end = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); |
540 | |
541 | Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); |
542 | Vector2 fog_near_size; |
543 | if (p_cam_projection.is_orthogonal()) { |
544 | fog_near_size = fog_far_size; |
545 | } else { |
546 | fog_near_size = Vector2(); |
547 | } |
548 | |
549 | params.fog_frustum_size_begin[0] = fog_near_size.x; |
550 | params.fog_frustum_size_begin[1] = fog_near_size.y; |
551 | |
552 | params.fog_frustum_size_end[0] = fog_far_size.x; |
553 | params.fog_frustum_size_end[1] = fog_far_size.y; |
554 | |
555 | params.fog_frustum_end = fog_end; |
556 | params.z_near = z_near; |
557 | params.z_far = z_far; |
558 | params.time = p_settings.time; |
559 | |
560 | params.fog_volume_size[0] = fog->width; |
561 | params.fog_volume_size[1] = fog->height; |
562 | params.fog_volume_size[2] = fog->depth; |
563 | |
564 | params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env); |
565 | params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; |
566 | params.detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); |
567 | params.temporal_blend = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection_amount(p_settings.env); |
568 | |
569 | Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; |
570 | RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); |
571 | RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform); |
572 | |
573 | RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); |
574 | |
575 | if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) { |
576 | Vector<RD::Uniform> uniforms; |
577 | |
578 | { |
579 | RD::Uniform u; |
580 | #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) |
581 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
582 | #else |
583 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
584 | #endif |
585 | u.binding = 1; |
586 | u.append_id(fog->emissive_map); |
587 | uniforms.push_back(u); |
588 | } |
589 | |
590 | { |
591 | RD::Uniform u; |
592 | u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; |
593 | u.binding = 2; |
594 | u.append_id(volumetric_fog.volume_ubo); |
595 | uniforms.push_back(u); |
596 | } |
597 | |
598 | { |
599 | RD::Uniform u; |
600 | #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) |
601 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
602 | #else |
603 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
604 | #endif |
605 | u.binding = 3; |
606 | u.append_id(fog->density_map); |
607 | uniforms.push_back(u); |
608 | } |
609 | |
610 | { |
611 | RD::Uniform u; |
612 | #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) |
613 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
614 | #else |
615 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
616 | #endif |
617 | u.binding = 4; |
618 | u.append_id(fog->light_map); |
619 | uniforms.push_back(u); |
620 | } |
621 | |
622 | fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); |
623 | } |
624 | |
625 | RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); |
626 | bool any_uses_time = false; |
627 | |
628 | for (int i = 0; i < (int)p_fog_volumes.size(); i++) { |
629 | FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]); |
630 | ERR_FAIL_COND(!fog_volume_instance); |
631 | RID fog_volume = fog_volume_instance->volume; |
632 | |
633 | RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume); |
634 | |
635 | FogMaterialData *material = nullptr; |
636 | |
637 | if (fog_material.is_valid()) { |
638 | material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); |
639 | if (!material || !material->shader_data->valid) { |
640 | material = nullptr; |
641 | } |
642 | } |
643 | |
644 | if (!material) { |
645 | fog_material = volumetric_fog.default_material; |
646 | material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); |
647 | } |
648 | |
649 | ERR_FAIL_COND(!material); |
650 | |
651 | FogShaderData *shader_data = material->shader_data; |
652 | |
653 | ERR_FAIL_COND(!shader_data); |
654 | |
655 | any_uses_time |= shader_data->uses_time; |
656 | |
657 | Vector3i min; |
658 | Vector3i max; |
659 | Vector3i kernel_size; |
660 | |
661 | Vector3 position = fog_volume_instance->transform.get_origin(); |
662 | RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); |
663 | Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_size(fog_volume) / 2; |
664 | |
665 | if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { |
666 | // Local fog volume. |
667 | Vector3i points[8]; |
668 | Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth); |
669 | float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); |
670 | 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); |
671 | 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); |
672 | points[2] = _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); |
673 | points[3] = _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); |
674 | points[4] = _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); |
675 | points[5] = _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); |
676 | 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); |
677 | 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); |
678 | |
679 | min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1); |
680 | max = Vector3i(1, 1, 1); |
681 | |
682 | for (int j = 0; j < 8; j++) { |
683 | min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z)); |
684 | max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z)); |
685 | } |
686 | |
687 | kernel_size = max - min; |
688 | } else { |
689 | // Volume type global runs on all cells |
690 | extents = Vector3(fog->width, fog->height, fog->depth); |
691 | min = Vector3i(0, 0, 0); |
692 | kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth)); |
693 | } |
694 | |
695 | if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) { |
696 | continue; |
697 | } |
698 | |
699 | VolumetricFogShader::FogPushConstant push_constant; |
700 | push_constant.position[0] = position.x; |
701 | push_constant.position[1] = position.y; |
702 | push_constant.position[2] = position.z; |
703 | push_constant.size[0] = extents.x * 2; |
704 | push_constant.size[1] = extents.y * 2; |
705 | push_constant.size[2] = extents.z * 2; |
706 | push_constant.corner[0] = min.x; |
707 | push_constant.corner[1] = min.y; |
708 | push_constant.corner[2] = min.z; |
709 | push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume)); |
710 | RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform); |
711 | |
712 | RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); |
713 | |
714 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); |
715 | RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant)); |
716 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE); |
717 | if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. |
718 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL); |
719 | material->set_as_used(); |
720 | } |
721 | |
722 | RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z); |
723 | } |
724 | if (any_uses_time || RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) { |
725 | RenderingServerDefault::redraw_request(); |
726 | } |
727 | |
728 | RD::get_singleton()->draw_command_end_label(); |
729 | |
730 | RD::get_singleton()->compute_list_end(); |
731 | } |
732 | |
733 | bool gi_dependent_sets_valid = fog->sync_gi_dependent_sets_validity(); |
734 | if (!fog->copy_uniform_set.is_null() && !RD::get_singleton()->uniform_set_is_valid(fog->copy_uniform_set)) { |
735 | fog->copy_uniform_set = RID(); |
736 | } |
737 | if (!gi_dependent_sets_valid || fog->copy_uniform_set.is_null()) { |
738 | //re create uniform set if needed |
739 | Vector<RD::Uniform> uniforms; |
740 | Vector<RD::Uniform> copy_uniforms; |
741 | |
742 | { |
743 | RD::Uniform u; |
744 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
745 | u.binding = 1; |
746 | if (p_settings.shadow_atlas_depth.is_null()) { |
747 | u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); |
748 | } else { |
749 | u.append_id(p_settings.shadow_atlas_depth); |
750 | } |
751 | |
752 | uniforms.push_back(u); |
753 | copy_uniforms.push_back(u); |
754 | } |
755 | |
756 | { |
757 | RD::Uniform u; |
758 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
759 | u.binding = 2; |
760 | if (p_settings.directional_shadow_depth.is_valid()) { |
761 | u.append_id(p_settings.directional_shadow_depth); |
762 | } else { |
763 | u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); |
764 | } |
765 | uniforms.push_back(u); |
766 | copy_uniforms.push_back(u); |
767 | } |
768 | |
769 | { |
770 | RD::Uniform u; |
771 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
772 | u.binding = 3; |
773 | u.append_id(p_settings.omni_light_buffer); |
774 | uniforms.push_back(u); |
775 | copy_uniforms.push_back(u); |
776 | } |
777 | { |
778 | RD::Uniform u; |
779 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
780 | u.binding = 4; |
781 | u.append_id(p_settings.spot_light_buffer); |
782 | uniforms.push_back(u); |
783 | copy_uniforms.push_back(u); |
784 | } |
785 | |
786 | { |
787 | RD::Uniform u; |
788 | u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; |
789 | u.binding = 5; |
790 | u.append_id(p_settings.directional_light_buffer); |
791 | uniforms.push_back(u); |
792 | copy_uniforms.push_back(u); |
793 | } |
794 | |
795 | { |
796 | RD::Uniform u; |
797 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
798 | u.binding = 6; |
799 | u.append_id(p_settings.cluster_builder->get_cluster_buffer()); |
800 | uniforms.push_back(u); |
801 | copy_uniforms.push_back(u); |
802 | } |
803 | |
804 | { |
805 | RD::Uniform u; |
806 | u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; |
807 | u.binding = 7; |
808 | u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); |
809 | uniforms.push_back(u); |
810 | copy_uniforms.push_back(u); |
811 | } |
812 | |
813 | { |
814 | RD::Uniform u; |
815 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
816 | u.binding = 8; |
817 | u.append_id(fog->light_density_map); |
818 | uniforms.push_back(u); |
819 | copy_uniforms.push_back(u); |
820 | } |
821 | |
822 | { |
823 | RD::Uniform u; |
824 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
825 | u.binding = 9; |
826 | u.append_id(fog->fog_map); |
827 | uniforms.push_back(u); |
828 | } |
829 | |
830 | { |
831 | RD::Uniform u; |
832 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
833 | u.binding = 9; |
834 | u.append_id(fog->prev_light_density_map); |
835 | copy_uniforms.push_back(u); |
836 | } |
837 | |
838 | { |
839 | RD::Uniform u; |
840 | u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; |
841 | u.binding = 10; |
842 | u.append_id(p_settings.shadow_sampler); |
843 | uniforms.push_back(u); |
844 | copy_uniforms.push_back(u); |
845 | } |
846 | |
847 | { |
848 | RD::Uniform u; |
849 | u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; |
850 | u.binding = 11; |
851 | u.append_id(p_settings.voxel_gi_buffer); |
852 | uniforms.push_back(u); |
853 | copy_uniforms.push_back(u); |
854 | } |
855 | |
856 | { |
857 | RD::Uniform u; |
858 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
859 | u.binding = 12; |
860 | for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) { |
861 | u.append_id(p_settings.rbgi->voxel_gi_textures[i]); |
862 | } |
863 | uniforms.push_back(u); |
864 | copy_uniforms.push_back(u); |
865 | } |
866 | { |
867 | RD::Uniform u; |
868 | u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; |
869 | u.binding = 13; |
870 | u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); |
871 | uniforms.push_back(u); |
872 | copy_uniforms.push_back(u); |
873 | } |
874 | { |
875 | RD::Uniform u; |
876 | u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; |
877 | u.binding = 14; |
878 | u.append_id(volumetric_fog.params_ubo); |
879 | uniforms.push_back(u); |
880 | copy_uniforms.push_back(u); |
881 | } |
882 | { |
883 | RD::Uniform u; |
884 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
885 | u.binding = 15; |
886 | u.append_id(fog->prev_light_density_map); |
887 | uniforms.push_back(u); |
888 | } |
889 | { |
890 | RD::Uniform u; |
891 | #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) |
892 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
893 | #else |
894 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
895 | #endif |
896 | u.binding = 16; |
897 | u.append_id(fog->density_map); |
898 | uniforms.push_back(u); |
899 | } |
900 | { |
901 | RD::Uniform u; |
902 | #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) |
903 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
904 | #else |
905 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
906 | #endif |
907 | u.binding = 17; |
908 | u.append_id(fog->light_map); |
909 | uniforms.push_back(u); |
910 | } |
911 | |
912 | { |
913 | RD::Uniform u; |
914 | #if defined(MACOS_ENABLED) || defined(IOS_ENABLED) |
915 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
916 | #else |
917 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
918 | #endif |
919 | u.binding = 18; |
920 | u.append_id(fog->emissive_map); |
921 | uniforms.push_back(u); |
922 | } |
923 | |
924 | { |
925 | RD::Uniform u; |
926 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
927 | u.binding = 19; |
928 | RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); |
929 | RID sky_texture = RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env).is_valid() ? p_settings.sky->sky_get_radiance_texture_rd(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env)) : RID(); |
930 | u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); |
931 | uniforms.push_back(u); |
932 | } |
933 | |
934 | if (fog->copy_uniform_set.is_null()) { |
935 | 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); |
936 | } |
937 | |
938 | if (!gi_dependent_sets_valid) { |
939 | fog->gi_dependent_sets.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); |
940 | |
941 | RID aux7 = uniforms.write[7].get_id(0); |
942 | RID aux8 = uniforms.write[8].get_id(0); |
943 | |
944 | uniforms.write[7].set_id(0, aux8); |
945 | uniforms.write[8].set_id(0, aux7); |
946 | |
947 | fog->gi_dependent_sets.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); |
948 | |
949 | uniforms.remove_at(8); |
950 | uniforms.write[7].set_id(0, aux7); |
951 | fog->gi_dependent_sets.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); |
952 | } |
953 | } |
954 | |
955 | 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()); |
956 | |
957 | if (using_sdfgi) { |
958 | if (fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->sdfgi_uniform_set)) { |
959 | Vector<RD::Uniform> uniforms; |
960 | |
961 | { |
962 | RD::Uniform u; |
963 | u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; |
964 | u.binding = 0; |
965 | u.append_id(p_settings.gi->sdfgi_ubo); |
966 | uniforms.push_back(u); |
967 | } |
968 | |
969 | { |
970 | RD::Uniform u; |
971 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
972 | u.binding = 1; |
973 | u.append_id(p_settings.sdfgi->ambient_texture); |
974 | uniforms.push_back(u); |
975 | } |
976 | |
977 | { |
978 | RD::Uniform u; |
979 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
980 | u.binding = 2; |
981 | u.append_id(p_settings.sdfgi->occlusion_texture); |
982 | uniforms.push_back(u); |
983 | } |
984 | |
985 | 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); |
986 | } |
987 | } |
988 | |
989 | fog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); |
990 | fog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); |
991 | |
992 | VolumetricFogShader::ParamsUBO params; |
993 | |
994 | Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents(); |
995 | Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents(); |
996 | float z_near = p_cam_projection.get_z_near(); |
997 | float z_far = p_cam_projection.get_z_far(); |
998 | float fog_end = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); |
999 | |
1000 | Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near)); |
1001 | Vector2 fog_near_size; |
1002 | if (p_cam_projection.is_orthogonal()) { |
1003 | fog_near_size = fog_far_size; |
1004 | } else { |
1005 | fog_near_size = Vector2(); |
1006 | } |
1007 | |
1008 | params.fog_frustum_size_begin[0] = fog_near_size.x; |
1009 | params.fog_frustum_size_begin[1] = fog_near_size.y; |
1010 | |
1011 | params.fog_frustum_size_end[0] = fog_far_size.x; |
1012 | params.fog_frustum_size_end[1] = fog_far_size.y; |
1013 | |
1014 | params.ambient_inject = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_ambient_inject(p_settings.env) * RendererSceneRenderRD::get_singleton()->environment_get_ambient_light_energy(p_settings.env); |
1015 | params.z_far = z_far; |
1016 | |
1017 | params.fog_frustum_end = fog_end; |
1018 | |
1019 | Color ambient_color = RendererSceneRenderRD::get_singleton()->environment_get_ambient_light(p_settings.env).srgb_to_linear(); |
1020 | params.ambient_color[0] = ambient_color.r; |
1021 | params.ambient_color[1] = ambient_color.g; |
1022 | params.ambient_color[2] = ambient_color.b; |
1023 | params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env); |
1024 | |
1025 | params.fog_volume_size[0] = fog->width; |
1026 | params.fog_volume_size[1] = fog->height; |
1027 | params.fog_volume_size[2] = fog->depth; |
1028 | |
1029 | params.directional_light_count = p_directional_light_count; |
1030 | |
1031 | Color emission = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission(p_settings.env).srgb_to_linear(); |
1032 | params.base_emission[0] = emission.r * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env); |
1033 | params.base_emission[1] = emission.g * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env); |
1034 | params.base_emission[2] = emission.b * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env); |
1035 | params.base_density = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_density(p_settings.env); |
1036 | |
1037 | Color base_scattering = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_scattering(p_settings.env).srgb_to_linear(); |
1038 | params.base_scattering[0] = base_scattering.r; |
1039 | params.base_scattering[1] = base_scattering.g; |
1040 | params.base_scattering[2] = base_scattering.b; |
1041 | params.phase_g = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_anisotropy(p_settings.env); |
1042 | |
1043 | params.detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); |
1044 | params.gi_inject = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env); |
1045 | |
1046 | params.cam_rotation[0] = p_cam_transform.basis[0][0]; |
1047 | params.cam_rotation[1] = p_cam_transform.basis[1][0]; |
1048 | params.cam_rotation[2] = p_cam_transform.basis[2][0]; |
1049 | params.cam_rotation[3] = 0; |
1050 | params.cam_rotation[4] = p_cam_transform.basis[0][1]; |
1051 | params.cam_rotation[5] = p_cam_transform.basis[1][1]; |
1052 | params.cam_rotation[6] = p_cam_transform.basis[2][1]; |
1053 | params.cam_rotation[7] = 0; |
1054 | params.cam_rotation[8] = p_cam_transform.basis[0][2]; |
1055 | params.cam_rotation[9] = p_cam_transform.basis[1][2]; |
1056 | params.cam_rotation[10] = p_cam_transform.basis[2][2]; |
1057 | params.cam_rotation[11] = 0; |
1058 | params.filter_axis = 0; |
1059 | params.max_voxel_gi_instances = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.001 ? p_voxel_gi_count : 0; |
1060 | params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; |
1061 | |
1062 | Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; |
1063 | RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); |
1064 | |
1065 | params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env); |
1066 | params.temporal_blend = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection_amount(p_settings.env); |
1067 | |
1068 | { |
1069 | uint32_t cluster_size = p_settings.cluster_builder->get_cluster_size(); |
1070 | params.cluster_shift = get_shift_from_power_of_2(cluster_size); |
1071 | |
1072 | uint32_t cluster_screen_width = (p_settings.rb_size.x - 1) / cluster_size + 1; |
1073 | uint32_t cluster_screen_height = (p_settings.rb_size.y - 1) / cluster_size + 1; |
1074 | params.max_cluster_element_count_div_32 = p_settings.max_cluster_elements / 32; |
1075 | params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32); |
1076 | params.cluster_width = cluster_screen_width; |
1077 | |
1078 | params.screen_size[0] = p_settings.rb_size.x; |
1079 | params.screen_size[1] = p_settings.rb_size.y; |
1080 | } |
1081 | |
1082 | Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_settings.env); |
1083 | sky_transform = sky_transform.inverse() * p_cam_transform.basis; |
1084 | RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform); |
1085 | |
1086 | RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog" ); |
1087 | |
1088 | RENDER_TIMESTAMP("Render Fog" ); |
1089 | RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); |
1090 | |
1091 | RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); |
1092 | |
1093 | 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]); |
1094 | |
1095 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set_density, 0); |
1096 | |
1097 | if (using_sdfgi) { |
1098 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1); |
1099 | } |
1100 | RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); |
1101 | RD::get_singleton()->compute_list_add_barrier(compute_list); |
1102 | |
1103 | // Copy fog to history buffer |
1104 | if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) { |
1105 | RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]); |
1106 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0); |
1107 | RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); |
1108 | RD::get_singleton()->compute_list_add_barrier(compute_list); |
1109 | } |
1110 | RD::get_singleton()->draw_command_end_label(); |
1111 | |
1112 | if (p_settings.volumetric_fog_filter_active) { |
1113 | RD::get_singleton()->draw_command_begin_label("Filter Fog" ); |
1114 | |
1115 | RENDER_TIMESTAMP("Filter Fog" ); |
1116 | |
1117 | RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); |
1118 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set, 0); |
1119 | RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); |
1120 | |
1121 | RD::get_singleton()->compute_list_end(); |
1122 | //need restart for buffer update |
1123 | |
1124 | params.filter_axis = 1; |
1125 | RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms); |
1126 | |
1127 | compute_list = RD::get_singleton()->compute_list_begin(); |
1128 | RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); |
1129 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set2, 0); |
1130 | RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); |
1131 | |
1132 | RD::get_singleton()->compute_list_add_barrier(compute_list); |
1133 | RD::get_singleton()->draw_command_end_label(); |
1134 | } |
1135 | |
1136 | RENDER_TIMESTAMP("Integrate Fog" ); |
1137 | RD::get_singleton()->draw_command_begin_label("Integrate Fog" ); |
1138 | |
1139 | RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]); |
1140 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set, 0); |
1141 | RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1); |
1142 | |
1143 | RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); |
1144 | |
1145 | RENDER_TIMESTAMP("< Volumetric Fog" ); |
1146 | RD::get_singleton()->draw_command_end_label(); |
1147 | RD::get_singleton()->draw_command_end_label(); |
1148 | } |
1149 | |