summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd/environment/sky.h
blob: 080165c112427a04c425b79c5716f01e634d0807 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
/*************************************************************************/
/*  sky.h                                                                */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#ifndef SKY_RD_H
#define SKY_RD_H

#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/environment/sky.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"

// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
class RendererSceneRenderRD;

namespace RendererRD {

class SkyRD {
public:
	enum SkySet {
		SKY_SET_UNIFORMS,
		SKY_SET_MATERIAL,
		SKY_SET_TEXTURES,
		SKY_SET_FOG,
		SKY_SET_MAX
	};

	// Skys need less info from Directional Lights than the normal shaders
	struct SkyDirectionalLightData {
		float direction[3];
		float energy;
		float color[3];
		float size;
		uint32_t enabled;
		uint32_t pad[3];
	};

private:
	RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;

	RID index_buffer;
	RID index_array;

	enum SkyTextureSetVersion {
		SKY_TEXTURE_SET_BACKGROUND,
		SKY_TEXTURE_SET_HALF_RES,
		SKY_TEXTURE_SET_QUARTER_RES,
		SKY_TEXTURE_SET_CUBEMAP,
		SKY_TEXTURE_SET_CUBEMAP_HALF_RES,
		SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES,
		SKY_TEXTURE_SET_MAX
	};

	enum SkyVersion {
		SKY_VERSION_BACKGROUND,
		SKY_VERSION_HALF_RES,
		SKY_VERSION_QUARTER_RES,
		SKY_VERSION_CUBEMAP,
		SKY_VERSION_CUBEMAP_HALF_RES,
		SKY_VERSION_CUBEMAP_QUARTER_RES,

		SKY_VERSION_BACKGROUND_MULTIVIEW,
		SKY_VERSION_HALF_RES_MULTIVIEW,
		SKY_VERSION_QUARTER_RES_MULTIVIEW,

		SKY_VERSION_MAX
	};

	struct SkyPushConstant {
		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
		// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
	};

	struct SkyShaderData : public RendererRD::MaterialStorage::ShaderData {
		bool valid = false;
		RID version;

		PipelineCacheRD pipelines[SKY_VERSION_MAX];
		HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
		Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;

		Vector<uint32_t> ubo_offsets;
		uint32_t ubo_size = 0;

		String path;
		String code;
		HashMap<StringName, HashMap<int, RID>> default_texture_params;

		bool uses_time = false;
		bool uses_position = false;
		bool uses_half_res = false;
		bool uses_quarter_res = false;
		bool uses_light = false;

		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 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_animated() const;
		virtual bool casts_shadows() const;
		virtual Variant get_default_parameter(const StringName &p_parameter) const;
		virtual RS::ShaderNativeSourceCode get_native_source_code() const;

		SkyShaderData() {}
		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);

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;
		};

		UBO ubo;

		SkyDirectionalLightData *directional_lights = nullptr;
		SkyDirectionalLightData *last_frame_directional_lights = nullptr;
		uint32_t max_directional_lights;
		uint32_t last_frame_directional_light_count;
		RID directional_light_buffer;
		RID uniform_set;
		RID uniform_buffer;
		RID fog_uniform_set;
		RID default_fog_uniform_set;

		RID fog_shader;
		RID fog_material;
		RID fog_only_texture_uniform_set;
	} sky_scene_state;

	struct ReflectionData {
		struct Layer {
			struct Mipmap {
				RID framebuffers[6];
				RID views[6];
				Size2i size;
			};
			Vector<Mipmap> mipmaps; //per-face view
			Vector<RID> views; // per-cubemap view
		};

		struct DownsampleLayer {
			struct Mipmap {
				RID view;
				Size2i size;

				// for mobile only
				RID views[6];
				RID framebuffers[6];
			};
			Vector<Mipmap> mipmaps;
		};

		RID radiance_base_cubemap; //cubemap for first layer, first cubemap
		RID downsampled_radiance_cubemap;
		DownsampleLayer downsampled_layer;
		RID coefficient_buffer;

		bool dirty = true;

		Vector<Layer> layers;

		void clear_reflection_data();
		void update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format);
		void create_reflection_fast_filter(bool p_use_arrays);
		void create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
		void update_reflection_mipmaps(int p_start, int p_end);
	};

	/* Sky shader */

	struct SkyShader {
		SkyShaderRD shader;
		ShaderCompiler compiler;

		RID default_shader;
		RID default_material;
		RID default_shader_rd;
	} sky_shader;

	struct SkyMaterialData : public RendererRD::MaterialStorage::MaterialData {
		SkyShaderData *shader_data = nullptr;
		RID uniform_set;
		bool uniform_set_updated;

		virtual void set_render_priority(int p_priority) {}
		virtual void set_next_pass(RID p_pass) {}
		virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
		virtual ~SkyMaterialData();
	};

	struct Sky {
		RID radiance;
		RID half_res_pass;
		RID half_res_framebuffer;
		RID quarter_res_pass;
		RID quarter_res_framebuffer;
		Size2i screen_size;

		RID texture_uniform_sets[SKY_TEXTURE_SET_MAX];
		RID uniform_set;

		RID material;
		RID uniform_buffer;

		int radiance_size = 256;

		RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC;

		ReflectionData reflection;
		bool dirty = false;
		int processing_layer = 0;
		Sky *dirty_list = nullptr;

		//State to track when radiance cubemap needs updating
		SkyMaterialData *prev_material = nullptr;
		Vector3 prev_position;
		float prev_time;

		void free();

		RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd);
		bool set_radiance_size(int p_radiance_size);
		bool set_mode(RS::SkyMode p_mode);
		bool set_material(RID p_material);
		Ref<Image> bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size);
	};

	uint32_t sky_ggx_samples_quality;
	bool sky_use_cubemap_array;
	Sky *dirty_sky_list = nullptr;
	mutable RID_Owner<Sky, true> sky_owner;
	int roughness_layers;

	RendererRD::MaterialStorage::ShaderData *_create_sky_shader_func();
	static RendererRD::MaterialStorage::ShaderData *_create_sky_shader_funcs();

	RendererRD::MaterialStorage::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
	static RendererRD::MaterialStorage::MaterialData *_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader);

	SkyRD();
	void init();
	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 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 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);

	void invalidate_sky(Sky *p_sky);
	void update_dirty_skys();

	RID sky_get_material(RID p_sky) const;

	RID allocate_sky_rid();
	void initialize_sky_rid(RID p_rid);
	Sky *get_sky(RID p_sky) const;
	void free_sky(RID p_sky);
	void sky_set_radiance_size(RID p_sky, int p_radiance_size);
	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

#endif // SKY_RD_H