1 | /**************************************************************************/ |
2 | /* render_forward_mobile.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 RENDER_FORWARD_MOBILE_H |
32 | #define RENDER_FORWARD_MOBILE_H |
33 | |
34 | #include "core/templates/paged_allocator.h" |
35 | #include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h" |
36 | #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" |
37 | #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" |
38 | #include "servers/rendering/renderer_rd/storage_rd/utilities.h" |
39 | |
40 | #define RB_SCOPE_MOBILE SNAME("mobile") |
41 | |
42 | namespace RendererSceneRenderImplementation { |
43 | |
44 | class RenderForwardMobile : public RendererSceneRenderRD { |
45 | friend SceneShaderForwardMobile; |
46 | |
47 | protected: |
48 | struct GeometryInstanceSurfaceDataCache; |
49 | |
50 | private: |
51 | static RenderForwardMobile *singleton; |
52 | |
53 | /* Scene Shader */ |
54 | |
55 | enum { |
56 | SCENE_UNIFORM_SET = 0, |
57 | RENDER_PASS_UNIFORM_SET = 1, |
58 | TRANSFORMS_UNIFORM_SET = 2, |
59 | MATERIAL_UNIFORM_SET = 3, |
60 | }; |
61 | |
62 | const int SAMPLERS_BINDING_FIRST_INDEX = 15; |
63 | |
64 | enum { |
65 | |
66 | SPEC_CONSTANT_USING_PROJECTOR = 0, |
67 | SPEC_CONSTANT_USING_SOFT_SHADOWS = 1, |
68 | SPEC_CONSTANT_USING_DIRECTIONAL_SOFT_SHADOWS = 2, |
69 | |
70 | SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 3, |
71 | SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 4, |
72 | SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 5, |
73 | SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 6, |
74 | |
75 | SPEC_CONSTANT_DECAL_USE_MIPMAPS = 7, |
76 | SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS = 8, |
77 | |
78 | SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 9, |
79 | SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 10, |
80 | SPEC_CONSTANT_DISABLE_REFLECTION_PROBES = 11, |
81 | SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 12, |
82 | |
83 | SPEC_CONSTANT_DISABLE_DECALS = 13, |
84 | SPEC_CONSTANT_DISABLE_FOG = 14, |
85 | |
86 | }; |
87 | |
88 | enum { |
89 | MAX_LIGHTMAPS = 8, |
90 | MAX_RDL_CULL = 8, // maximum number of reflection probes, decals or lights we can cull per geometry instance |
91 | INSTANCE_DATA_BUFFER_MIN_SIZE = 4096 |
92 | }; |
93 | |
94 | enum RenderListType { |
95 | RENDER_LIST_OPAQUE, //used for opaque objects |
96 | RENDER_LIST_ALPHA, //used for transparent objects |
97 | RENDER_LIST_SECONDARY, //used for shadows and other objects |
98 | RENDER_LIST_MAX |
99 | }; |
100 | |
101 | /* Scene Shader */ |
102 | |
103 | SceneShaderForwardMobile scene_shader; |
104 | |
105 | /* Render Buffer */ |
106 | |
107 | class RenderBufferDataForwardMobile : public RenderBufferCustomDataRD { |
108 | GDCLASS(RenderBufferDataForwardMobile, RenderBufferCustomDataRD); |
109 | |
110 | public: |
111 | // We can have: |
112 | // - 4 subpasses combining the full render cycle |
113 | // - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer) |
114 | // - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer) |
115 | enum FramebufferConfigType { |
116 | FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass |
117 | FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass |
118 | FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass |
119 | FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass |
120 | FB_CONFIG_MAX |
121 | }; |
122 | |
123 | RID get_color_fbs(FramebufferConfigType p_config_type); |
124 | virtual void free_data() override; |
125 | virtual void configure(RenderSceneBuffersRD *p_render_buffers) override; |
126 | |
127 | private: |
128 | RenderSceneBuffersRD *render_buffers = nullptr; |
129 | }; |
130 | |
131 | virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override; |
132 | |
133 | /* Rendering */ |
134 | |
135 | enum PassMode { |
136 | PASS_MODE_COLOR, |
137 | // PASS_MODE_COLOR_SPECULAR, |
138 | PASS_MODE_COLOR_TRANSPARENT, |
139 | PASS_MODE_SHADOW, |
140 | PASS_MODE_SHADOW_DP, |
141 | // PASS_MODE_DEPTH, |
142 | // PASS_MODE_DEPTH_NORMAL_ROUGHNESS, |
143 | // PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI, |
144 | PASS_MODE_DEPTH_MATERIAL, |
145 | // PASS_MODE_SDF, |
146 | }; |
147 | |
148 | struct RenderElementInfo; |
149 | |
150 | struct RenderListParameters { |
151 | GeometryInstanceSurfaceDataCache **elements = nullptr; |
152 | RenderElementInfo *element_info = nullptr; |
153 | int element_count = 0; |
154 | bool reverse_cull = false; |
155 | PassMode pass_mode = PASS_MODE_COLOR; |
156 | // bool no_gi = false; |
157 | uint32_t view_count = 1; |
158 | RID render_pass_uniform_set; |
159 | bool force_wireframe = false; |
160 | Vector2 uv_offset; |
161 | uint32_t spec_constant_base_flags = 0; |
162 | float lod_distance_multiplier = 0.0; |
163 | float screen_mesh_lod_threshold = 0.0; |
164 | RD::FramebufferFormatID framebuffer_format = 0; |
165 | uint32_t element_offset = 0; |
166 | uint32_t barrier = RD::BARRIER_MASK_ALL_BARRIERS; |
167 | uint32_t subpass = 0; |
168 | |
169 | RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS) { |
170 | elements = p_elements; |
171 | element_info = p_element_info; |
172 | element_count = p_element_count; |
173 | reverse_cull = p_reverse_cull; |
174 | pass_mode = p_pass_mode; |
175 | // no_gi = p_no_gi; |
176 | view_count = p_view_count; |
177 | render_pass_uniform_set = p_render_pass_uniform_set; |
178 | force_wireframe = p_force_wireframe; |
179 | uv_offset = p_uv_offset; |
180 | lod_distance_multiplier = p_lod_distance_multiplier; |
181 | screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; |
182 | element_offset = p_element_offset; |
183 | barrier = p_barrier; |
184 | spec_constant_base_flags = p_spec_constant_base_flags; |
185 | } |
186 | }; |
187 | |
188 | /* Render shadows */ |
189 | |
190 | void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr); |
191 | void _render_shadow_begin(); |
192 | void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr); |
193 | void _render_shadow_process(); |
194 | void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS); |
195 | |
196 | /* Render Scene */ |
197 | |
198 | RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); |
199 | void _pre_opaque_render(RenderDataRD *p_render_data); |
200 | |
201 | uint64_t lightmap_texture_array_version = 0xFFFFFFFF; |
202 | |
203 | void _update_render_base_uniform_set(); |
204 | |
205 | void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false); |
206 | void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1); |
207 | // void _update_instance_data_buffer(RenderListType p_render_list); |
208 | |
209 | void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); |
210 | void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform); |
211 | |
212 | RID render_base_uniform_set; |
213 | LocalVector<RID> render_pass_uniform_sets; |
214 | |
215 | /* Light map */ |
216 | |
217 | struct LightmapData { |
218 | float normal_xform[12]; |
219 | float pad[3]; |
220 | float exposure_normalization; |
221 | }; |
222 | |
223 | struct LightmapCaptureData { |
224 | float sh[9 * 4]; |
225 | }; |
226 | |
227 | /* Scene state */ |
228 | |
229 | struct SceneState { |
230 | LocalVector<RID> uniform_buffers; |
231 | |
232 | // !BAS! We need to change lightmaps, we're not going to do this with a buffer but pushing the used lightmap in |
233 | LightmapData lightmaps[MAX_LIGHTMAPS]; |
234 | RID lightmap_ids[MAX_LIGHTMAPS]; |
235 | bool lightmap_has_sh[MAX_LIGHTMAPS]; |
236 | uint32_t lightmaps_used = 0; |
237 | uint32_t max_lightmaps; |
238 | RID lightmap_buffer; |
239 | |
240 | LightmapCaptureData *lightmap_captures = nullptr; |
241 | uint32_t max_lightmap_captures; |
242 | RID lightmap_capture_buffer; |
243 | |
244 | bool used_screen_texture = false; |
245 | bool used_normal_texture = false; |
246 | bool used_depth_texture = false; |
247 | bool used_sss = false; |
248 | |
249 | struct ShadowPass { |
250 | uint32_t element_from; |
251 | uint32_t element_count; |
252 | bool flip_cull; |
253 | PassMode pass_mode; |
254 | |
255 | RID rp_uniform_set; |
256 | Plane camera_plane; |
257 | float lod_distance_multiplier; |
258 | float screen_mesh_lod_threshold; |
259 | |
260 | RID framebuffer; |
261 | RD::InitialAction initial_depth_action; |
262 | RD::FinalAction final_depth_action; |
263 | Rect2i rect; |
264 | }; |
265 | |
266 | LocalVector<ShadowPass> shadow_passes; |
267 | } scene_state; |
268 | |
269 | /* Render List */ |
270 | |
271 | // !BAS! Render list can probably be reused between clustered and mobile? |
272 | struct RenderList { |
273 | LocalVector<GeometryInstanceSurfaceDataCache *> elements; |
274 | LocalVector<RenderElementInfo> element_info; |
275 | |
276 | void clear() { |
277 | elements.clear(); |
278 | element_info.clear(); |
279 | } |
280 | |
281 | //should eventually be replaced by radix |
282 | |
283 | struct SortByKey { |
284 | _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { |
285 | return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2); |
286 | } |
287 | }; |
288 | |
289 | void sort_by_key() { |
290 | SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter; |
291 | sorter.sort(elements.ptr(), elements.size()); |
292 | } |
293 | |
294 | void sort_by_key_range(uint32_t p_from, uint32_t p_size) { |
295 | SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter; |
296 | sorter.sort(elements.ptr() + p_from, p_size); |
297 | } |
298 | |
299 | struct SortByDepth { |
300 | _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { |
301 | return (A->owner->depth < B->owner->depth); |
302 | } |
303 | }; |
304 | |
305 | void sort_by_depth() { //used for shadows |
306 | |
307 | SortArray<GeometryInstanceSurfaceDataCache *, SortByDepth> sorter; |
308 | sorter.sort(elements.ptr(), elements.size()); |
309 | } |
310 | |
311 | struct SortByReverseDepthAndPriority { |
312 | _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { |
313 | return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority); |
314 | } |
315 | }; |
316 | |
317 | void sort_by_reverse_depth_and_priority() { //used for alpha |
318 | |
319 | SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter; |
320 | sorter.sort(elements.ptr(), elements.size()); |
321 | } |
322 | |
323 | _FORCE_INLINE_ void add_element(GeometryInstanceSurfaceDataCache *p_element) { |
324 | elements.push_back(p_element); |
325 | } |
326 | }; |
327 | |
328 | struct RenderElementInfo { |
329 | uint32_t uses_lightmap : 1; |
330 | uint32_t lod_index : 8; |
331 | uint32_t reserved : 23; |
332 | }; |
333 | |
334 | template <PassMode p_pass_mode> |
335 | _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); |
336 | |
337 | void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); |
338 | |
339 | LocalVector<RD::DrawListID> thread_draw_lists; |
340 | void _render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params); |
341 | void _render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); |
342 | |
343 | uint32_t render_list_thread_threshold = 500; |
344 | |
345 | RenderList render_list[RENDER_LIST_MAX]; |
346 | |
347 | protected: |
348 | /* setup */ |
349 | virtual void _update_shader_quality_settings() override; |
350 | |
351 | virtual float _render_buffers_get_luminance_multiplier() override; |
352 | virtual RD::DataFormat _render_buffers_get_color_format() override; |
353 | virtual bool _render_buffers_can_be_storage() override; |
354 | |
355 | virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; |
356 | virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; |
357 | |
358 | virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{}; |
359 | virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{}; |
360 | virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override{}; |
361 | |
362 | virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override{}; |
363 | virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override{}; |
364 | |
365 | /* Geometry instance */ |
366 | |
367 | class GeometryInstanceForwardMobile; |
368 | |
369 | // When changing any of these enums, remember to change the corresponding enums in the shader files as well. |
370 | enum { |
371 | INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4, |
372 | INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5, |
373 | INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 6, |
374 | INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 7, |
375 | INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 8, |
376 | INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 9, |
377 | INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 10, |
378 | INSTANCE_DATA_FLAG_PARTICLES = 1 << 11, |
379 | INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, |
380 | INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, |
381 | INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, |
382 | INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, |
383 | INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16, |
384 | INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF, |
385 | }; |
386 | |
387 | struct GeometryInstanceLightmapSH { |
388 | Color sh[9]; |
389 | }; |
390 | |
391 | // Cached data for drawing surfaces |
392 | struct GeometryInstanceSurfaceDataCache { |
393 | enum { |
394 | FLAG_PASS_DEPTH = 1, |
395 | FLAG_PASS_OPAQUE = 2, |
396 | FLAG_PASS_ALPHA = 4, |
397 | FLAG_PASS_SHADOW = 8, |
398 | FLAG_USES_SHARED_SHADOW_MATERIAL = 128, |
399 | FLAG_USES_SUBSURFACE_SCATTERING = 2048, |
400 | FLAG_USES_SCREEN_TEXTURE = 4096, |
401 | FLAG_USES_DEPTH_TEXTURE = 8192, |
402 | FLAG_USES_NORMAL_TEXTURE = 16384, |
403 | FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768, |
404 | FLAG_USES_PARTICLE_TRAILS = 65536, |
405 | }; |
406 | |
407 | union { |
408 | struct { |
409 | // !BAS! CHECK BITS!!! |
410 | |
411 | uint64_t surface_index : 10; |
412 | uint64_t geometry_id : 32; |
413 | uint64_t material_id_low : 16; |
414 | |
415 | uint64_t material_id_hi : 16; |
416 | uint64_t shader_id : 32; |
417 | uint64_t uses_lightmap : 4; // sort by lightmap id here, not whether its yes/no (is 4 bits enough?) |
418 | uint64_t depth_layer : 4; |
419 | uint64_t priority : 8; |
420 | |
421 | // uint64_t lod_index : 8; // no need to sort on LOD |
422 | // uint64_t uses_forward_gi : 1; // no GI here, remove |
423 | }; |
424 | struct { |
425 | uint64_t sort_key1; |
426 | uint64_t sort_key2; |
427 | }; |
428 | } sort; |
429 | |
430 | RS::PrimitiveType primitive = RS::PRIMITIVE_MAX; |
431 | uint32_t flags = 0; |
432 | uint32_t surface_index = 0; |
433 | uint32_t lod_index = 0; |
434 | |
435 | void *surface = nullptr; |
436 | RID material_uniform_set; |
437 | SceneShaderForwardMobile::ShaderData *shader = nullptr; |
438 | SceneShaderForwardMobile::MaterialData *material = nullptr; |
439 | |
440 | void *surface_shadow = nullptr; |
441 | RID material_uniform_set_shadow; |
442 | SceneShaderForwardMobile::ShaderData *shader_shadow = nullptr; |
443 | |
444 | GeometryInstanceSurfaceDataCache *next = nullptr; |
445 | GeometryInstanceForwardMobile *owner = nullptr; |
446 | }; |
447 | |
448 | class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase { |
449 | public: |
450 | // this structure maps to our push constant in our shader and is populated right before our draw call |
451 | struct PushConstant { |
452 | float transform[16]; |
453 | uint32_t flags; |
454 | uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables |
455 | uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index) |
456 | uint32_t layer_mask = 1; |
457 | float lightmap_uv_scale[4]; // doubles as uv_offset when needed |
458 | uint32_t reflection_probes[2]; // packed reflection probes |
459 | uint32_t omni_lights[2]; // packed omni lights |
460 | uint32_t spot_lights[2]; // packed spot lights |
461 | uint32_t decals[2]; // packed spot lights |
462 | }; |
463 | |
464 | // PushConstant push_constant; // we populate this from our instance data |
465 | |
466 | //used during rendering |
467 | RID transforms_uniform_set; |
468 | bool use_projector = false; |
469 | bool use_soft_shadow = false; |
470 | bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform |
471 | uint32_t instance_count = 0; |
472 | uint32_t trail_steps = 1; |
473 | |
474 | // lightmap |
475 | uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap |
476 | RID lightmap_instance; |
477 | Rect2 lightmap_uv_scale; |
478 | uint32_t lightmap_slice_index; |
479 | GeometryInstanceLightmapSH *lightmap_sh = nullptr; |
480 | |
481 | // culled light info |
482 | uint32_t reflection_probe_count = 0; |
483 | RendererRD::ForwardID reflection_probes[MAX_RDL_CULL]; |
484 | uint32_t omni_light_count = 0; |
485 | RendererRD::ForwardID omni_lights[MAX_RDL_CULL]; |
486 | uint32_t spot_light_count = 0; |
487 | RendererRD::ForwardID spot_lights[MAX_RDL_CULL]; |
488 | uint32_t decals_count = 0; |
489 | RendererRD::ForwardID decals[MAX_RDL_CULL]; |
490 | |
491 | GeometryInstanceSurfaceDataCache *surface_caches = nullptr; |
492 | |
493 | // do we use this? |
494 | SelfList<GeometryInstanceForwardMobile> dirty_list_element; |
495 | |
496 | GeometryInstanceForwardMobile() : |
497 | dirty_list_element(this) {} |
498 | |
499 | virtual void _mark_dirty() override; |
500 | |
501 | virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override; |
502 | virtual void set_lightmap_capture(const Color *p_sh9) override; |
503 | |
504 | virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override; |
505 | virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override; |
506 | virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override; |
507 | virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {} |
508 | |
509 | virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override; |
510 | }; |
511 | |
512 | /* Rendering */ |
513 | |
514 | virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; |
515 | |
516 | virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override; |
517 | virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; |
518 | virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; |
519 | virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; |
520 | |
521 | /* Forward ID */ |
522 | |
523 | class ForwardIDStorageMobile : public RendererRD::ForwardIDStorage { |
524 | public: |
525 | struct ForwardIDAllocator { |
526 | LocalVector<bool> allocations; |
527 | LocalVector<uint8_t> map; |
528 | }; |
529 | |
530 | ForwardIDAllocator forward_id_allocators[RendererRD::FORWARD_ID_MAX]; |
531 | |
532 | public: |
533 | virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) override; |
534 | virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) override; |
535 | virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) override; |
536 | virtual bool uses_forward_ids() const override { return true; } |
537 | |
538 | void fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance); |
539 | }; |
540 | |
541 | ForwardIDStorageMobile *forward_id_storage_mobile = nullptr; |
542 | |
543 | virtual RendererRD::ForwardIDStorage *create_forward_id_storage() override { |
544 | forward_id_storage_mobile = memnew(ForwardIDStorageMobile); |
545 | return forward_id_storage_mobile; |
546 | } |
547 | |
548 | public: |
549 | static RenderForwardMobile *get_singleton() { return singleton; } |
550 | |
551 | virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override; |
552 | |
553 | /* SDFGI UPDATE */ |
554 | |
555 | virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} |
556 | virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; } |
557 | virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); } |
558 | virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; } |
559 | |
560 | /* GEOMETRY INSTANCE */ |
561 | |
562 | static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker); |
563 | static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker); |
564 | |
565 | SelfList<GeometryInstanceForwardMobile>::List geometry_instance_dirty_list; |
566 | |
567 | PagedAllocator<GeometryInstanceForwardMobile> geometry_instance_alloc; |
568 | PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc; |
569 | PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh; |
570 | |
571 | void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); |
572 | void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh); |
573 | void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); |
574 | void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance); |
575 | void _update_dirty_geometry_instances(); |
576 | |
577 | virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override; |
578 | virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override; |
579 | |
580 | virtual uint32_t geometry_instance_get_pair_mask() override; |
581 | |
582 | virtual bool free(RID p_rid) override; |
583 | |
584 | virtual void base_uniforms_changed() override; |
585 | |
586 | virtual bool is_dynamic_gi_supported() const override; |
587 | virtual bool is_volumetric_supported() const override; |
588 | virtual uint32_t get_max_elements() const override; |
589 | |
590 | RenderForwardMobile(); |
591 | ~RenderForwardMobile(); |
592 | }; |
593 | } // namespace RendererSceneRenderImplementation |
594 | |
595 | #endif // RENDER_FORWARD_MOBILE_H |
596 | |