1/**************************************************************************/
2/* fog.h */
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#ifndef FOG_RD_H
32#define FOG_RD_H
33
34#include "core/templates/local_vector.h"
35#include "core/templates/rid_owner.h"
36#include "servers/rendering/environment/renderer_fog.h"
37#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
38#include "servers/rendering/renderer_rd/environment/gi.h"
39#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"
40#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h"
41#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
42#include "servers/rendering/storage/utilities.h"
43
44#define RB_SCOPE_FOG SNAME("Fog")
45
46namespace RendererRD {
47
48class Fog : public RendererFog {
49private:
50 static Fog *singleton;
51
52 /* FOG VOLUMES */
53
54 struct FogVolume {
55 RID material;
56 Vector3 size = Vector3(2, 2, 2);
57
58 RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
59
60 Dependency dependency;
61 };
62
63 mutable RID_Owner<FogVolume, true> fog_volume_owner;
64
65 struct FogVolumeInstance {
66 RID volume;
67 Transform3D transform;
68 bool active = false;
69 };
70
71 mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
72
73 const int SAMPLERS_BINDING_FIRST_INDEX = 3;
74
75 /* Volumetric Fog */
76 struct VolumetricFogShader {
77 enum FogSet {
78 FOG_SET_BASE,
79 FOG_SET_UNIFORMS,
80 FOG_SET_MATERIAL,
81 FOG_SET_MAX,
82 };
83
84 struct FogPushConstant {
85 float position[3];
86 float pad;
87
88 float size[3];
89 float pad2;
90
91 int32_t corner[3];
92 uint32_t shape;
93
94 float transform[16];
95 };
96
97 struct VolumeUBO {
98 float fog_frustum_size_begin[2];
99 float fog_frustum_size_end[2];
100
101 float fog_frustum_end;
102 float z_near;
103 float z_far;
104 float time;
105
106 int32_t fog_volume_size[3];
107 uint32_t directional_light_count;
108
109 uint32_t use_temporal_reprojection;
110 uint32_t temporal_frame;
111 float detail_spread;
112 float temporal_blend;
113
114 float to_prev_view[16];
115 float transform[16];
116 };
117
118 ShaderCompiler compiler;
119 VolumetricFogShaderRD shader;
120 RID volume_ubo;
121
122 RID default_shader;
123 RID default_material;
124 RID default_shader_rd;
125
126 RID base_uniform_set;
127
128 RID params_ubo;
129
130 enum {
131 VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
132 VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
133 VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
134 VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
135 VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
136 VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
137 };
138
139 struct ParamsUBO {
140 float fog_frustum_size_begin[2];
141 float fog_frustum_size_end[2];
142
143 float fog_frustum_end;
144 float ambient_inject;
145 float z_far;
146 uint32_t filter_axis;
147
148 float ambient_color[3];
149 float sky_contribution;
150
151 int32_t fog_volume_size[3];
152 uint32_t directional_light_count;
153
154 float base_emission[3];
155 float base_density;
156
157 float base_scattering[3];
158 float phase_g;
159
160 float detail_spread;
161 float gi_inject;
162 uint32_t max_voxel_gi_instances;
163 uint32_t cluster_type_size;
164
165 float screen_size[2];
166 uint32_t cluster_shift;
167 uint32_t cluster_width;
168
169 uint32_t max_cluster_element_count_div_32;
170 uint32_t use_temporal_reprojection;
171 uint32_t temporal_frame;
172 float temporal_blend;
173
174 float cam_rotation[12];
175 float to_prev_view[16];
176 float radiance_inverse_xform[12];
177 };
178
179 VolumetricFogProcessShaderRD process_shader;
180
181 RID process_shader_version;
182 RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
183
184 } volumetric_fog;
185
186 Vector3i _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);
187
188 struct FogShaderData : public RendererRD::MaterialStorage::ShaderData {
189 bool valid = false;
190 RID version;
191
192 RID pipeline;
193 Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
194
195 Vector<uint32_t> ubo_offsets;
196 uint32_t ubo_size = 0;
197
198 String code;
199
200 bool uses_time = false;
201
202 virtual void set_code(const String &p_Code);
203 virtual bool is_animated() const;
204 virtual bool casts_shadows() const;
205 virtual RS::ShaderNativeSourceCode get_native_source_code() const;
206
207 FogShaderData() {}
208 virtual ~FogShaderData();
209 };
210
211 struct FogMaterialData : public RendererRD::MaterialStorage::MaterialData {
212 FogShaderData *shader_data = nullptr;
213 RID uniform_set;
214 bool uniform_set_updated;
215
216 virtual void set_render_priority(int p_priority) {}
217 virtual void set_next_pass(RID p_pass) {}
218 virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
219 virtual ~FogMaterialData();
220 };
221
222 RendererRD::MaterialStorage::ShaderData *_create_fog_shader_func();
223 static RendererRD::MaterialStorage::ShaderData *_create_fog_shader_funcs();
224
225 RendererRD::MaterialStorage::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
226 static RendererRD::MaterialStorage::MaterialData *_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader);
227
228public:
229 static Fog *get_singleton() { return singleton; }
230
231 Fog();
232 ~Fog();
233
234 /* FOG VOLUMES */
235
236 bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); };
237
238 virtual RID fog_volume_allocate() override;
239 virtual void fog_volume_initialize(RID p_rid) override;
240 virtual void fog_volume_free(RID p_rid) override;
241 Dependency *fog_volume_get_dependency(RID p_fog_volume) const;
242
243 virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;
244 virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override;
245 virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override;
246 virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override;
247 RID fog_volume_get_material(RID p_fog_volume) const;
248 virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override;
249 Vector3 fog_volume_get_size(RID p_fog_volume) const;
250
251 /* FOG VOLUMES INSTANCE */
252
253 bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); };
254
255 RID fog_volume_instance_create(RID p_fog_volume);
256 void fog_instance_free(RID p_rid);
257
258 void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
259 Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
260 ERR_FAIL_COND(!fvi);
261 fvi->transform = p_transform;
262 }
263
264 void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
265 Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
266 ERR_FAIL_COND(!fvi);
267 fvi->active = p_active;
268 }
269
270 RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
271 Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
272 ERR_FAIL_COND_V(!fvi, RID());
273 return fvi->volume;
274 }
275
276 Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const {
277 Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
278 ERR_FAIL_COND_V(!fvi, Vector3());
279 return fvi->transform.get_origin();
280 }
281
282 /* Volumetric FOG */
283 class VolumetricFog : public RenderBufferCustomDataRD {
284 GDCLASS(VolumetricFog, RenderBufferCustomDataRD)
285
286 public:
287 enum {
288 MAX_TEMPORAL_FRAMES = 16
289 };
290
291 uint32_t width = 0;
292 uint32_t height = 0;
293 uint32_t depth = 0;
294
295 float length;
296 float spread;
297
298 RID light_density_map;
299 RID prev_light_density_map;
300 RID fog_map;
301 RID density_map;
302 RID light_map;
303 RID emissive_map;
304
305 RID fog_uniform_set;
306 RID copy_uniform_set;
307
308 struct {
309 RID process_uniform_set_density;
310 RID process_uniform_set;
311 RID process_uniform_set2;
312 } gi_dependent_sets;
313
314 RID sdfgi_uniform_set;
315 RID sky_uniform_set;
316
317 int last_shadow_filter = -1;
318
319 virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
320 virtual void free_data() override{};
321
322 bool sync_gi_dependent_sets_validity(bool p_ensure_freed = false);
323
324 void init(const Vector3i &fog_size, RID p_sky_shader);
325 ~VolumetricFog();
326 };
327
328 void init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array);
329 void free_fog_shader();
330
331 struct VolumetricFogSettings {
332 Vector2i rb_size;
333 double time;
334 bool is_using_radiance_cubemap_array;
335 uint32_t max_cluster_elements;
336 bool volumetric_fog_filter_active;
337 RID shadow_sampler;
338 RID voxel_gi_buffer;
339 RID shadow_atlas_depth;
340 RID omni_light_buffer;
341 RID spot_light_buffer;
342 RID directional_shadow_depth;
343 RID directional_light_buffer;
344
345 // Objects related to our render buffer
346 Ref<VolumetricFog> vfog;
347 ClusterBuilderRD *cluster_builder;
348 GI *gi;
349 Ref<GI::SDFGI> sdfgi;
350 Ref<GI::RenderBuffersGI> rbgi;
351 RID env;
352 SkyRD *sky;
353 };
354 void 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);
355};
356
357} // namespace RendererRD
358
359#endif // FOG_RD_H
360