diff options
Diffstat (limited to 'servers/rendering')
| -rw-r--r-- | servers/rendering/SCsub | 2 | ||||
| -rw-r--r-- | servers/rendering/rasterizer.h | 1413 | ||||
| -rw-r--r-- | servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h | 602 | ||||
| -rw-r--r-- | servers/rendering/rasterizer_rd/shaders/ssao.glsl | 249 | ||||
| -rw-r--r-- | servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl | 153 | ||||
| -rw-r--r-- | servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl | 45 | ||||
| -rw-r--r-- | servers/rendering/renderer_canvas_cull.cpp (renamed from servers/rendering/rendering_server_canvas.cpp) | 507 | ||||
| -rw-r--r-- | servers/rendering/renderer_canvas_cull.h (renamed from servers/rendering/rendering_server_canvas.h) | 48 | ||||
| -rw-r--r-- | servers/rendering/renderer_canvas_render.cpp | 31 | ||||
| -rw-r--r-- | servers/rendering/renderer_canvas_render.h | 604 | ||||
| -rw-r--r-- | servers/rendering/renderer_compositor.cpp | 42 | ||||
| -rw-r--r-- | servers/rendering/renderer_compositor.h | 78 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/SCsub (renamed from servers/rendering/rasterizer_rd/SCsub) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/effects_rd.cpp (renamed from servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp) | 678 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/effects_rd.h (renamed from servers/rendering/rasterizer_rd/rasterizer_effects_rd.h) | 230 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/light_cluster_builder.cpp (renamed from servers/rendering/rasterizer_rd/light_cluster_builder.cpp) | 6 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/light_cluster_builder.h (renamed from servers/rendering/rasterizer_rd/light_cluster_builder.h) | 6 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/pipeline_cache_rd.cpp (renamed from servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp) | 22 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/pipeline_cache_rd.h (renamed from servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h) | 16 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp (renamed from servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp) | 280 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_canvas_render_rd.h (renamed from servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h) | 53 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_compositor_rd.cpp (renamed from servers/rendering/rasterizer_rd/rasterizer_rd.cpp) | 38 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_compositor_rd.h (renamed from servers/rendering/rasterizer_rd/rasterizer_rd.h) | 44 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_forward.cpp (renamed from servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp) | 2101 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_forward.h | 745 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_rd.cpp (renamed from servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp) | 1601 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_rd.h (renamed from servers/rendering/rasterizer_rd/rasterizer_scene_rd.h) | 188 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_storage_rd.cpp (renamed from servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp) | 1679 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_storage_rd.h (renamed from servers/rendering/rasterizer_rd/rasterizer_storage_rd.h) | 332 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shader_compiler_rd.cpp (renamed from servers/rendering/rasterizer_rd/shader_compiler_rd.cpp) | 35 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shader_compiler_rd.h (renamed from servers/rendering/rasterizer_rd/shader_compiler_rd.h) | 4 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shader_rd.cpp (renamed from servers/rendering/rasterizer_rd/shader_rd.cpp) | 153 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shader_rd.h (renamed from servers/rendering/rasterizer_rd/shader_rd.h) | 12 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/SCsub (renamed from servers/rendering/rasterizer_rd/shaders/SCsub) | 7 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/bokeh_dof.glsl (renamed from servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/canvas.glsl (renamed from servers/rendering/rasterizer_rd/shaders/canvas.glsl) | 25 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl (renamed from servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/canvas_sdf.glsl (renamed from servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl (renamed from servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl (renamed from servers/rendering/rasterizer_rd/shaders/cluster_data_inc.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/copy.glsl (renamed from servers/rendering/rasterizer_rd/shaders/copy.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/copy_to_fb.glsl (renamed from servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/cube_to_dp.glsl (renamed from servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl (renamed from servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/cubemap_filter.glsl (renamed from servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl (renamed from servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/gi.glsl (renamed from servers/rendering/rasterizer_rd/shaders/gi.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/giprobe.glsl (renamed from servers/rendering/rasterizer_rd/shaders/giprobe.glsl) | 11 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/giprobe_debug.glsl (renamed from servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl (renamed from servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/giprobe_write.glsl (renamed from servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/luminance_reduce.glsl (renamed from servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/particles.glsl (renamed from servers/rendering/rasterizer_rd/shaders/particles.glsl) | 2 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/particles_copy.glsl (renamed from servers/rendering/rasterizer_rd/shaders/particles_copy.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/resolve.glsl (renamed from servers/rendering/rasterizer_rd/shaders/resolve.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/roughness_limiter.glsl (renamed from servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/scene_forward.glsl (renamed from servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl) | 234 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl (renamed from servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl) | 100 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl (renamed from servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl (renamed from servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl (renamed from servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl (renamed from servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl (renamed from servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl (renamed from servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl) | 14 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/sdfgi_fields.glsl (renamed from servers/rendering/rasterizer_rd/shaders/sdfgi_fields.glsl) | 2 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl (renamed from servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl (renamed from servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/shadow_reduce.glsl (renamed from servers/rendering/rasterizer_rd/shaders/shadow_reduce.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/skeleton.glsl | 199 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/sky.glsl (renamed from servers/rendering/rasterizer_rd/shaders/sky.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/sort.glsl (renamed from servers/rendering/rasterizer_rd/shaders/sort.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/specular_merge.glsl (renamed from servers/rendering/rasterizer_rd/shaders/specular_merge.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/ssao.glsl | 486 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/ssao_blur.glsl | 154 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/ssao_downsample.glsl | 206 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl | 126 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/ssao_interleave.glsl | 119 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl (renamed from servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl) | 0 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/tonemap.glsl (renamed from servers/rendering/rasterizer_rd/shaders/tonemap.glsl) | 24 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/volumetric_fog.glsl (renamed from servers/rendering/rasterizer_rd/shaders/volumetric_fog.glsl) | 21 | ||||
| -rw-r--r-- | servers/rendering/renderer_scene.cpp | 37 | ||||
| -rw-r--r-- | servers/rendering/renderer_scene.h | 203 | ||||
| -rw-r--r-- | servers/rendering/renderer_scene_cull.cpp | 3508 | ||||
| -rw-r--r-- | servers/rendering/renderer_scene_cull.h | 1045 | ||||
| -rw-r--r-- | servers/rendering/renderer_scene_render.cpp | 31 | ||||
| -rw-r--r-- | servers/rendering/renderer_scene_render.h | 230 | ||||
| -rw-r--r-- | servers/rendering/renderer_storage.cpp (renamed from servers/rendering/rasterizer.cpp) | 46 | ||||
| -rw-r--r-- | servers/rendering/renderer_storage.h | 623 | ||||
| -rw-r--r-- | servers/rendering/renderer_thread_pool.cpp | 42 | ||||
| -rw-r--r-- | servers/rendering/renderer_thread_pool.h | 45 | ||||
| -rw-r--r-- | servers/rendering/renderer_viewport.cpp (renamed from servers/rendering/rendering_server_viewport.cpp) | 218 | ||||
| -rw-r--r-- | servers/rendering/renderer_viewport.h (renamed from servers/rendering/rendering_server_viewport.h) | 18 | ||||
| -rw-r--r-- | servers/rendering/rendering_device.cpp | 10 | ||||
| -rw-r--r-- | servers/rendering/rendering_device.h | 15 | ||||
| -rw-r--r-- | servers/rendering/rendering_device_binds.cpp | 6 | ||||
| -rw-r--r-- | servers/rendering/rendering_device_binds.h | 12 | ||||
| -rw-r--r-- | servers/rendering/rendering_server_default.cpp (renamed from servers/rendering/rendering_server_raster.cpp) | 112 | ||||
| -rw-r--r-- | servers/rendering/rendering_server_default.h (renamed from servers/rendering/rendering_server_raster.h) | 49 | ||||
| -rw-r--r-- | servers/rendering/rendering_server_globals.cpp | 17 | ||||
| -rw-r--r-- | servers/rendering/rendering_server_globals.h | 27 | ||||
| -rw-r--r-- | servers/rendering/rendering_server_scene.cpp | 3040 | ||||
| -rw-r--r-- | servers/rendering/rendering_server_scene.h | 476 | ||||
| -rw-r--r-- | servers/rendering/rendering_server_wrap_mt.cpp | 4 | ||||
| -rw-r--r-- | servers/rendering/rendering_server_wrap_mt.h | 29 | ||||
| -rw-r--r-- | servers/rendering/shader_language.cpp | 469 | ||||
| -rw-r--r-- | servers/rendering/shader_language.h | 16 | ||||
| -rw-r--r-- | servers/rendering/shader_types.cpp | 20 | ||||
| -rw-r--r-- | servers/rendering/shader_types.h | 4 |
108 files changed, 14466 insertions, 9613 deletions
diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub index 5ea0d40486..0939b68482 100644 --- a/servers/rendering/SCsub +++ b/servers/rendering/SCsub @@ -4,4 +4,4 @@ Import("env") env.add_source_files(env.servers_sources, "*.cpp") -SConscript("rasterizer_rd/SCsub") +SConscript("renderer_rd/SCsub") diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h deleted file mode 100644 index 4df140f8c3..0000000000 --- a/servers/rendering/rasterizer.h +++ /dev/null @@ -1,1413 +0,0 @@ -/*************************************************************************/ -/* rasterizer.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 RASTERIZER_H -#define RASTERIZER_H - -#include "core/math/camera_matrix.h" -#include "core/templates/pair.h" -#include "core/templates/self_list.h" -#include "servers/rendering_server.h" - -class RasterizerScene { -public: - /* SHADOW ATLAS API */ - - virtual RID shadow_atlas_create() = 0; - virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0; - virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0; - virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0; - - virtual void directional_shadow_atlas_set_size(int p_size) = 0; - virtual int get_directional_light_shadow_size(RID p_light_intance) = 0; - virtual void set_directional_shadow_count(int p_count) = 0; - - /* SDFGI UPDATE */ - - struct InstanceBase; - - virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0; - virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0; - virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0; - virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0; - virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0; - - /* SKY API */ - - virtual RID sky_create() = 0; - virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; - virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0; - virtual void sky_set_material(RID p_sky, RID p_material) = 0; - virtual Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0; - - /* ENVIRONMENT API */ - - virtual RID environment_create() = 0; - - virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0; - virtual void environment_set_sky(RID p_env, RID p_sky) = 0; - virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; - virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; - virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; - virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; - virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; -#endif - - virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0; - virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; - virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; - - virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0; - - virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0; - virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0; - virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) = 0; - virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) = 0; - - virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0; - virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0; - - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; - - virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; - - virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; - - virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0; - virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0; - - virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; - - virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; - - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; - - virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; - - virtual bool is_environment(RID p_env) const = 0; - virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0; - virtual int environment_get_canvas_max_layer(RID p_env) const = 0; - - virtual RID camera_effects_create() = 0; - - virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0; - virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0; - - virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; - virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; - - virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0; - virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0; - - struct InstanceDependency { - void instance_notify_changed(bool p_aabb, bool p_dependencies); - void instance_notify_deleted(RID p_deleted); - - ~InstanceDependency(); - - private: - friend struct InstanceBase; - Map<InstanceBase *, uint32_t> instances; - }; - - struct InstanceBase { - RS::InstanceType base_type; - RID base; - - RID skeleton; - RID material_override; - - RID instance_data; - - Transform transform; - - int depth_layer; - uint32_t layer_mask; - uint32_t instance_version; - - //RID sampled_light; - - Vector<RID> materials; - Vector<RID> light_instances; - Vector<RID> reflection_probe_instances; - Vector<RID> gi_probe_instances; - - Vector<float> blend_values; - - RS::ShadowCastingSetting cast_shadows; - - //fit in 32 bits - bool mirror : 8; - bool receive_shadows : 8; - bool visible : 8; - bool baked_light : 2; //this flag is only to know if it actually did use baked light - bool dynamic_gi : 2; //this flag is only to know if it actually did use baked light - bool redraw_if_visible : 4; - - float depth; //used for sorting - - SelfList<InstanceBase> dependency_item; - - InstanceBase *lightmap; - Rect2 lightmap_uv_scale; - int lightmap_slice_index; - uint32_t lightmap_cull_index; - Vector<Color> lightmap_sh; //spherical harmonic - - AABB aabb; - AABB transformed_aabb; - - struct InstanceShaderParameter { - int32_t index = -1; - Variant value; - Variant default_value; - PropertyInfo info; - }; - - Map<StringName, InstanceShaderParameter> instance_shader_parameters; - bool instance_allocated_shader_parameters = false; - int32_t instance_allocated_shader_parameters_offset = -1; - - virtual void dependency_deleted(RID p_dependency) {} - virtual void dependency_changed(bool p_aabb, bool p_dependencies) {} - - Set<InstanceDependency *> dependencies; - - void instance_increase_version() { - instance_version++; - } - - void update_dependency(InstanceDependency *p_dependency) { - dependencies.insert(p_dependency); - p_dependency->instances[this] = instance_version; - } - - void clean_up_dependencies() { - List<Pair<InstanceDependency *, Map<InstanceBase *, uint32_t>::Element *>> to_clean_up; - for (Set<InstanceDependency *>::Element *E = dependencies.front(); E; E = E->next()) { - InstanceDependency *dep = E->get(); - Map<InstanceBase *, uint32_t>::Element *F = dep->instances.find(this); - ERR_CONTINUE(!F); - if (F->get() != instance_version) { - Pair<InstanceDependency *, Map<InstanceBase *, uint32_t>::Element *> p; - p.first = dep; - p.second = F; - to_clean_up.push_back(p); - } - } - - while (to_clean_up.size()) { - to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second); - to_clean_up.pop_front(); - } - } - - void clear_dependencies() { - for (Set<InstanceDependency *>::Element *E = dependencies.front(); E; E = E->next()) { - InstanceDependency *dep = E->get(); - dep->instances.erase(this); - } - dependencies.clear(); - } - - InstanceBase() : - dependency_item(this) { - base_type = RS::INSTANCE_NONE; - cast_shadows = RS::SHADOW_CASTING_SETTING_ON; - receive_shadows = true; - visible = true; - depth_layer = 0; - layer_mask = 1; - instance_version = 0; - baked_light = false; - dynamic_gi = false; - redraw_if_visible = false; - lightmap_slice_index = 0; - lightmap = nullptr; - lightmap_cull_index = 0; - } - - virtual ~InstanceBase() { - clear_dependencies(); - } - }; - - virtual RID light_instance_create(RID p_light) = 0; - virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0; - virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0; - virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0; - virtual void light_instance_mark_visible(RID p_light_instance) = 0; - virtual bool light_instances_can_render_shadow_cube() const { - return true; - } - - virtual RID reflection_atlas_create() = 0; - virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0; - - virtual RID reflection_probe_instance_create(RID p_probe) = 0; - virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0; - virtual void reflection_probe_release_atlas_index(RID p_instance) = 0; - virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0; - virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0; - virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0; - virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0; - - virtual RID decal_instance_create(RID p_decal) = 0; - virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform) = 0; - - virtual RID gi_probe_instance_create(RID p_gi_probe) = 0; - virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0; - virtual bool gi_probe_needs_update(RID p_probe) const = 0; - virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0; - - virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0; - - virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; - - virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0; - virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; - virtual void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) = 0; - virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) = 0; - virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count) = 0; - - virtual void set_scene_pass(uint64_t p_pass) = 0; - virtual void set_time(double p_time, double p_step) = 0; - virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; - - virtual RID render_buffers_create() = 0; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0; - - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; - virtual bool screen_space_roughness_limiter_is_active() const = 0; - - virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0; - virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0; - - virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0; - - virtual bool free(RID p_rid) = 0; - - virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0; - - virtual void update() = 0; - virtual ~RasterizerScene() {} -}; - -class RasterizerStorage { - Color default_clear_color; - -public: - /* TEXTURE API */ - - virtual RID texture_2d_create(const Ref<Image> &p_image) = 0; - virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; - virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; - virtual RID texture_proxy_create(RID p_base) = 0; //all slices, then all the mipmaps, must be coherent - - virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming - virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; - virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; - virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; - - //these two APIs can be used together or in combination with the others. - virtual RID texture_2d_placeholder_create() = 0; - virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type) = 0; - virtual RID texture_3d_placeholder_create() = 0; - - virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; - virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; - virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; - - virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; - - virtual void texture_set_path(RID p_texture, const String &p_path) = 0; - virtual String texture_get_path(RID p_texture) const = 0; - - virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; - - virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0; - - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; - - virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; - - virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; - virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; - - /* CANVAS TEXTURE API */ - - virtual RID canvas_texture_create() = 0; - virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; - virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; - - virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; - virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; - - /* SHADER API */ - - virtual RID shader_create() = 0; - - virtual void shader_set_code(RID p_shader, const String &p_code) = 0; - virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; - virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; - - /* COMMON MATERIAL API */ - - virtual RID material_create() = 0; - - virtual void material_set_render_priority(RID p_material, int priority) = 0; - virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; - - virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; - virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; - - virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; - - virtual bool material_is_animated(RID p_material) = 0; - virtual bool material_casts_shadows(RID p_material) = 0; - - struct InstanceShaderParam { - PropertyInfo info; - int index; - Variant default_value; - }; - - virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; - - virtual void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0; - - /* MESH API */ - - virtual RID mesh_create() = 0; - - /// Returns stride - virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0; - - virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0; - virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; - - virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; - - virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; - - virtual int mesh_get_surface_count(RID p_mesh) const = 0; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; - virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; - - virtual void mesh_clear(RID p_mesh) = 0; - - /* MULTIMESH API */ - - virtual RID multimesh_create() = 0; - - virtual void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; - - virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; - - virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; - virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0; - virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; - virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; - virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; - - virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; - - virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; - virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; - - virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0; - virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0; - - virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; - virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; - - virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; - - /* IMMEDIATE API */ - - virtual RID immediate_create() = 0; - virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0; - virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0; - virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0; - virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0; - virtual void immediate_color(RID p_immediate, const Color &p_color) = 0; - virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_end(RID p_immediate) = 0; - virtual void immediate_clear(RID p_immediate) = 0; - virtual void immediate_set_material(RID p_immediate, RID p_material) = 0; - virtual RID immediate_get_material(RID p_immediate) const = 0; - virtual AABB immediate_get_aabb(RID p_immediate) const = 0; - - /* SKELETON API */ - - virtual RID skeleton_create() = 0; - virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; - virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; - virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0; - virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; - virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; - - /* Light API */ - - virtual RID light_create(RS::LightType p_type) = 0; - - RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); } - RID omni_light_create() { return light_create(RS::LIGHT_OMNI); } - RID spot_light_create() { return light_create(RS::LIGHT_SPOT); } - - virtual void light_set_color(RID p_light, const Color &p_color) = 0; - virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0; - virtual void light_set_shadow(RID p_light, bool p_enabled) = 0; - virtual void light_set_shadow_color(RID p_light, const Color &p_color) = 0; - virtual void light_set_projector(RID p_light, RID p_texture) = 0; - virtual void light_set_negative(RID p_light, bool p_enable) = 0; - virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; - virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; - virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0; - virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0; - - virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0; - - virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0; - virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; - virtual bool light_directional_get_blend_splits(RID p_light) const = 0; - virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0; - virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0; - - virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0; - virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0; - - virtual bool light_has_shadow(RID p_light) const = 0; - - virtual RS::LightType light_get_type(RID p_light) const = 0; - virtual AABB light_get_aabb(RID p_light) const = 0; - virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0; - virtual Color light_get_color(RID p_light) = 0; - virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0; - virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0; - virtual uint64_t light_get_version(RID p_light) const = 0; - - /* PROBE API */ - - virtual RID reflection_probe_create() = 0; - - virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0; - virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0; - virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0; - virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0; - virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0; - virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0; - virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; - virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; - virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0; - - virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0; - virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0; - virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0; - virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0; - virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0; - virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0; - virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0; - - virtual void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0; - virtual void skeleton_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0; - - /* DECAL API */ - - virtual RID decal_create() = 0; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0; - virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0; - virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0; - virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0; - virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0; - virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0; - virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0; - virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0; - virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0; - - virtual AABB decal_get_aabb(RID p_decal) const = 0; - - /* GI PROBE API */ - - virtual RID gi_probe_create() = 0; - - virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0; - - virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0; - virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0; - virtual Vector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const = 0; - virtual Vector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const = 0; - virtual Vector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const = 0; - - virtual Vector<int> gi_probe_get_level_counts(RID p_gi_probe) const = 0; - virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0; - virtual float gi_probe_get_energy(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0; - virtual float gi_probe_get_ao(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0; - virtual float gi_probe_get_bias(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; - - virtual uint32_t gi_probe_get_version(RID p_probe) = 0; - - /* LIGHTMAP CAPTURE */ - - virtual RID lightmap_create() = 0; - - virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0; - virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0; - virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0; - virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0; - virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0; - virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0; - virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0; - virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0; - virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0; - virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0; - virtual bool lightmap_is_interior(RID p_lightmap) const = 0; - virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0; - virtual float lightmap_get_probe_capture_update_speed() const = 0; - - /* PARTICLES */ - - virtual RID particles_create() = 0; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; - virtual bool particles_get_emitting(RID p_particles) = 0; - - virtual void particles_set_amount(RID p_particles, int p_amount) = 0; - virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0; - virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; - virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0; - virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0; - virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0; - virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0; - virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0; - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; - virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; - virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; - virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; - virtual void particles_set_collision_base_size(RID p_particles, float p_size) = 0; - virtual void particles_restart(RID p_particles) = 0; - virtual void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0; - virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0; - - virtual bool particles_is_inactive(RID p_particles) const = 0; - - virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0; - - virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; - virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; - - virtual void particles_request_process(RID p_particles) = 0; - virtual AABB particles_get_current_aabb(RID p_particles) = 0; - virtual AABB particles_get_aabb(RID p_particles) const = 0; - - virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; - - virtual int particles_get_draw_passes(RID p_particles) const = 0; - virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0; - - virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis) = 0; - - virtual void particles_add_collision(RID p_particles, RasterizerScene::InstanceBase *p_instance) = 0; - virtual void particles_remove_collision(RID p_particles, RasterizerScene::InstanceBase *p_instance) = 0; - - virtual void update_particles() = 0; - - /* PARTICLES COLLISION */ - - virtual RID particles_collision_create() = 0; - virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0; - virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0; - virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) = 0; //for spheres - virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres - virtual void particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) = 0; - virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) = 0; - virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) = 0; - virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic - virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field - virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field - virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0; - virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0; - virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0; - - /* GLOBAL VARIABLES */ - - virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0; - virtual void global_variable_remove(const StringName &p_name) = 0; - virtual Vector<StringName> global_variable_get_list() const = 0; - - virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0; - virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0; - virtual Variant global_variable_get(const StringName &p_name) const = 0; - virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0; - - virtual void global_variables_load_settings(bool p_load_textures = true) = 0; - virtual void global_variables_clear() = 0; - - virtual int32_t global_variables_instance_allocate(RID p_instance) = 0; - virtual void global_variables_instance_free(RID p_instance) = 0; - virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; - - /* RENDER TARGET */ - - enum RenderTargetFlags { - RENDER_TARGET_TRANSPARENT, - RENDER_TARGET_DIRECT_TO_SCREEN, - RENDER_TARGET_FLAG_MAX - }; - - virtual RID render_target_create() = 0; - virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; - virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0; - virtual RID render_target_get_texture(RID p_render_target) = 0; - virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0; - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0; - virtual bool render_target_was_used(RID p_render_target) = 0; - virtual void render_target_set_as_unused(RID p_render_target) = 0; - - virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0; - virtual bool render_target_is_clear_requested(RID p_render_target) = 0; - virtual Color render_target_get_clear_request_color(RID p_render_target) = 0; - virtual void render_target_disable_clear_request(RID p_render_target) = 0; - virtual void render_target_do_clear_request(RID p_render_target) = 0; - - virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0; - virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0; - - virtual RS::InstanceType get_base_type(RID p_rid) const = 0; - virtual bool free(RID p_rid) = 0; - - virtual bool has_os_feature(const String &p_feature) const = 0; - - virtual void update_dirty_resources() = 0; - - virtual void set_debug_generate_wireframes(bool p_generate) = 0; - - virtual void render_info_begin_capture() = 0; - virtual void render_info_end_capture() = 0; - virtual int get_captured_render_info(RS::RenderInfo p_info) = 0; - - virtual int get_render_info(RS::RenderInfo p_info) = 0; - virtual String get_video_adapter_name() const = 0; - virtual String get_video_adapter_vendor() const = 0; - - static RasterizerStorage *base_singleton; - - void set_default_clear_color(const Color &p_color) { - default_clear_color = p_color; - } - - Color get_default_clear_color() const { - return default_clear_color; - } -#define TIMESTAMP_BEGIN() \ - { \ - if (RSG::storage->capturing_timestamps) \ - RSG::storage->capture_timestamps_begin(); \ - } - -#define RENDER_TIMESTAMP(m_text) \ - { \ - if (RSG::storage->capturing_timestamps) \ - RSG::storage->capture_timestamp(m_text); \ - } - - bool capturing_timestamps = false; - - virtual void capture_timestamps_begin() = 0; - virtual void capture_timestamp(const String &p_name) = 0; - virtual uint32_t get_captured_timestamps_count() const = 0; - virtual uint64_t get_captured_timestamps_frame() const = 0; - virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0; - virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0; - virtual String get_captured_timestamp_name(uint32_t p_index) const = 0; - - RasterizerStorage(); - virtual ~RasterizerStorage() {} -}; - -class RasterizerCanvas { -public: - static RasterizerCanvas *singleton; - - enum CanvasRectFlags { - CANVAS_RECT_REGION = 1, - CANVAS_RECT_TILE = 2, - CANVAS_RECT_FLIP_H = 4, - CANVAS_RECT_FLIP_V = 8, - CANVAS_RECT_TRANSPOSE = 16, - CANVAS_RECT_CLIP_UV = 32, - CANVAS_RECT_IS_GROUP = 64, - }; - - struct Light { - bool enabled; - Color color; - Transform2D xform; - float height; - float energy; - float scale; - int z_min; - int z_max; - int layer_min; - int layer_max; - int item_mask; - int item_shadow_mask; - float directional_distance; - RS::CanvasLightMode mode; - RS::CanvasLightBlendMode blend_mode; - RID texture; - Vector2 texture_offset; - RID canvas; - bool use_shadow; - int shadow_buffer_size; - RS::CanvasLightShadowFilter shadow_filter; - Color shadow_color; - float shadow_smooth; - - //void *texture_cache; // implementation dependent - Rect2 rect_cache; - Transform2D xform_cache; - float radius_cache; //used for shadow far plane - //CameraMatrix shadow_matrix_cache; - - Transform2D light_shader_xform; - //Vector2 light_shader_pos; - - Light *shadows_next_ptr; - Light *filter_next_ptr; - Light *next_ptr; - Light *directional_next_ptr; - - RID light_internal; - uint64_t version; - - int32_t render_index_cache; - - Light() { - version = 0; - enabled = true; - color = Color(1, 1, 1); - shadow_color = Color(0, 0, 0, 0); - height = 0; - z_min = -1024; - z_max = 1024; - layer_min = 0; - layer_max = 0; - item_mask = 1; - scale = 1.0; - energy = 1.0; - item_shadow_mask = 1; - mode = RS::CANVAS_LIGHT_MODE_POINT; - blend_mode = RS::CANVAS_LIGHT_BLEND_MODE_ADD; - // texture_cache = nullptr; - next_ptr = nullptr; - directional_next_ptr = nullptr; - filter_next_ptr = nullptr; - use_shadow = false; - shadow_buffer_size = 2048; - shadow_filter = RS::CANVAS_LIGHT_FILTER_NONE; - shadow_smooth = 0.0; - render_index_cache = -1; - directional_distance = 10000.0; - } - }; - - //easier wrap to avoid mistakes - - struct Item; - - typedef uint64_t PolygonID; - virtual PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) = 0; - virtual void free_polygon(PolygonID p_polygon) = 0; - - //also easier to wrap to avoid mistakes - struct Polygon { - PolygonID polygon_id; - Rect2 rect_cache; - - _FORCE_INLINE_ void create(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) { - ERR_FAIL_COND(polygon_id != 0); - { - uint32_t pc = p_points.size(); - const Vector2 *v2 = p_points.ptr(); - rect_cache.position = *v2; - for (uint32_t i = 1; i < pc; i++) { - rect_cache.expand_to(v2[i]); - } - } - polygon_id = singleton->request_polygon(p_indices, p_points, p_colors, p_uvs, p_bones, p_weights); - } - - _FORCE_INLINE_ Polygon() { polygon_id = 0; } - _FORCE_INLINE_ ~Polygon() { - if (polygon_id) { - singleton->free_polygon(polygon_id); - } - } - }; - - //item - - struct Item { - //commands are allocated in blocks of 4k to improve performance - //and cache coherence. - //blocks always grow but never shrink. - - struct CommandBlock { - enum { - MAX_SIZE = 4096 - }; - uint32_t usage; - uint8_t *memory; - }; - - struct Command { - enum Type { - TYPE_RECT, - TYPE_NINEPATCH, - TYPE_POLYGON, - TYPE_PRIMITIVE, - TYPE_MESH, - TYPE_MULTIMESH, - TYPE_PARTICLES, - TYPE_TRANSFORM, - TYPE_CLIP_IGNORE, - }; - - Command *next; - Type type; - virtual ~Command() {} - }; - - struct CommandRect : public Command { - Rect2 rect; - Color modulate; - Rect2 source; - uint8_t flags; - - RID texture; - - CommandRect() { - flags = 0; - type = TYPE_RECT; - } - }; - - struct CommandNinePatch : public Command { - Rect2 rect; - Rect2 source; - float margin[4]; - bool draw_center; - Color color; - RS::NinePatchAxisMode axis_x; - RS::NinePatchAxisMode axis_y; - - RID texture; - - CommandNinePatch() { - draw_center = true; - type = TYPE_NINEPATCH; - } - }; - - struct CommandPolygon : public Command { - RS::PrimitiveType primitive; - Polygon polygon; - - RID texture; - - CommandPolygon() { - type = TYPE_POLYGON; - } - }; - - struct CommandPrimitive : public Command { - uint32_t point_count; - Vector2 points[4]; - Vector2 uvs[4]; - Color colors[4]; - - RID texture; - - CommandPrimitive() { - type = TYPE_PRIMITIVE; - } - }; - - struct CommandMesh : public Command { - RID mesh; - Transform2D transform; - Color modulate; - - RID texture; - - CommandMesh() { type = TYPE_MESH; } - }; - - struct CommandMultiMesh : public Command { - RID multimesh; - - RID texture; - - CommandMultiMesh() { type = TYPE_MULTIMESH; } - }; - - struct CommandParticles : public Command { - RID particles; - - RID texture; - - CommandParticles() { type = TYPE_PARTICLES; } - }; - - struct CommandTransform : public Command { - Transform2D xform; - CommandTransform() { type = TYPE_TRANSFORM; } - }; - - struct CommandClipIgnore : public Command { - bool ignore; - CommandClipIgnore() { - type = TYPE_CLIP_IGNORE; - ignore = false; - } - }; - - struct ViewportRender { - RenderingServer *owner; - void *udata; - Rect2 rect; - }; - - Transform2D xform; - bool clip; - bool visible; - bool behind; - bool update_when_visible; - - struct CanvasGroup { - RS::CanvasGroupMode mode; - bool fit_empty; - float fit_margin; - bool blur_mipmaps; - float clear_margin; - }; - - CanvasGroup *canvas_group = nullptr; - int light_mask; - int z_final; - - mutable bool custom_rect; - mutable bool rect_dirty; - mutable Rect2 rect; - RID material; - RID skeleton; - - Item *next; - - struct CopyBackBuffer { - Rect2 rect; - Rect2 screen_rect; - bool full; - }; - CopyBackBuffer *copy_back_buffer; - - Color final_modulate; - Transform2D final_transform; - Rect2 final_clip_rect; - Item *final_clip_owner; - Item *material_owner; - Item *canvas_group_owner; - ViewportRender *vp_render; - bool distance_field; - bool light_masked; - - Rect2 global_rect_cache; - - const Rect2 &get_rect() const { - if (custom_rect || (!rect_dirty && !update_when_visible)) { - return rect; - } - - //must update rect - - if (commands == nullptr) { - rect = Rect2(); - rect_dirty = false; - return rect; - } - - Transform2D xf; - bool found_xform = false; - bool first = true; - - const Item::Command *c = commands; - - while (c) { - Rect2 r; - - switch (c->type) { - case Item::Command::TYPE_RECT: { - const Item::CommandRect *crect = static_cast<const Item::CommandRect *>(c); - r = crect->rect; - - } break; - case Item::Command::TYPE_NINEPATCH: { - const Item::CommandNinePatch *style = static_cast<const Item::CommandNinePatch *>(c); - r = style->rect; - } break; - - case Item::Command::TYPE_POLYGON: { - const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c); - r = polygon->polygon.rect_cache; - } break; - case Item::Command::TYPE_PRIMITIVE: { - const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c); - for (uint32_t j = 0; j < primitive->point_count; j++) { - if (j == 0) { - r.position = primitive->points[0]; - } else { - r.expand_to(primitive->points[j]); - } - } - } break; - case Item::Command::TYPE_MESH: { - const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c); - AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID()); - - r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); - - } break; - case Item::Command::TYPE_MULTIMESH: { - const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c); - AABB aabb = RasterizerStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh); - - r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); - - } break; - case Item::Command::TYPE_PARTICLES: { - const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c); - if (particles_cmd->particles.is_valid()) { - AABB aabb = RasterizerStorage::base_singleton->particles_get_aabb(particles_cmd->particles); - r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); - } - - } break; - case Item::Command::TYPE_TRANSFORM: { - const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c); - xf = transform->xform; - found_xform = true; - [[fallthrough]]; - } - default: { - c = c->next; - continue; - } - } - - if (found_xform) { - r = xf.xform(r); - found_xform = false; - } - - if (first) { - rect = r; - first = false; - } else { - rect = rect.merge(r); - } - c = c->next; - } - - rect_dirty = false; - return rect; - } - - Command *commands; - Command *last_command; - Vector<CommandBlock> blocks; - uint32_t current_block; - - template <class T> - T *alloc_command() { - T *command; - if (commands == nullptr) { - // As the most common use case of canvas items is to - // use only one command, the first is done with it's - // own allocation. The rest of them use blocks. - command = memnew(T); - command->next = nullptr; - commands = command; - last_command = command; - } else { - //Subsequent commands go into a block. - - while (true) { - if (unlikely(current_block == (uint32_t)blocks.size())) { - // If we need more blocks, we allocate them - // (they won't be freed until this CanvasItem is - // deleted, though). - CommandBlock cb; - cb.memory = (uint8_t *)memalloc(CommandBlock::MAX_SIZE); - cb.usage = 0; - blocks.push_back(cb); - } - - CommandBlock *c = &blocks.write[current_block]; - size_t space_left = CommandBlock::MAX_SIZE - c->usage; - if (space_left < sizeof(T)) { - current_block++; - continue; - } - - //allocate block and add to the linked list - void *memory = c->memory + c->usage; - command = memnew_placement(memory, T); - command->next = nullptr; - last_command->next = command; - last_command = command; - c->usage += sizeof(T); - break; - } - } - - rect_dirty = true; - return command; - } - - void clear() { - // The first one is always allocated on heap - // the rest go in the blocks - Command *c = commands; - while (c) { - Command *n = c->next; - if (c == commands) { - memdelete(commands); - commands = nullptr; - } else { - c->~Command(); - } - c = n; - } - { - uint32_t cbc = MIN((current_block + 1), (uint32_t)blocks.size()); - CommandBlock *blockptr = blocks.ptrw(); - for (uint32_t i = 0; i < cbc; i++) { - blockptr[i].usage = 0; - } - } - - last_command = nullptr; - commands = nullptr; - current_block = 0; - clip = false; - rect_dirty = true; - final_clip_owner = nullptr; - material_owner = nullptr; - light_masked = false; - } - - RS::CanvasItemTextureFilter texture_filter; - RS::CanvasItemTextureRepeat texture_repeat; - - Item() { - commands = nullptr; - last_command = nullptr; - current_block = 0; - light_mask = 1; - vp_render = nullptr; - next = nullptr; - final_clip_owner = nullptr; - canvas_group_owner = nullptr; - clip = false; - final_modulate = Color(1, 1, 1, 1); - visible = true; - rect_dirty = true; - custom_rect = false; - behind = false; - material_owner = nullptr; - copy_back_buffer = nullptr; - distance_field = false; - light_masked = false; - update_when_visible = false; - z_final = 0; - texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - } - virtual ~Item() { - clear(); - for (int i = 0; i < blocks.size(); i++) { - memfree(blocks[i].memory); - } - if (copy_back_buffer) { - memdelete(copy_back_buffer); - } - } - }; - - virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) = 0; - virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0; - - struct LightOccluderInstance { - bool enabled; - RID canvas; - RID polygon; - RID occluder; - Rect2 aabb_cache; - Transform2D xform; - Transform2D xform_cache; - int light_mask; - bool sdf_collision; - RS::CanvasOccluderPolygonCullMode cull_cache; - - LightOccluderInstance *next; - - LightOccluderInstance() { - enabled = true; - sdf_collision = false; - next = nullptr; - light_mask = 1; - cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; - } - }; - - virtual RID light_create() = 0; - virtual void light_set_texture(RID p_rid, RID p_texture) = 0; - virtual void light_set_use_shadow(RID p_rid, bool p_enable) = 0; - virtual void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0; - virtual void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) = 0; - - virtual void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) = 0; - - virtual RID occluder_polygon_create() = 0; - virtual void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) = 0; - virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0; - virtual void set_shadow_texture_size(int p_size) = 0; - - virtual void draw_window_margins(int *p_margins, RID *p_margin_textures) = 0; - - virtual bool free(RID p_rid) = 0; - virtual void update() = 0; - - RasterizerCanvas() { singleton = this; } - virtual ~RasterizerCanvas() {} -}; - -class Rasterizer { -protected: - static Rasterizer *(*_create_func)(); - -public: - static Rasterizer *create(); - - virtual RasterizerStorage *get_storage() = 0; - virtual RasterizerCanvas *get_canvas() = 0; - virtual RasterizerScene *get_scene() = 0; - - virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0; - - virtual void initialize() = 0; - virtual void begin_frame(double frame_step) = 0; - - struct BlitToScreen { - RID render_target; - Rect2i rect; - //lens distorted parameters for VR should go here - }; - - virtual void prepare_for_blitting_render_targets() = 0; - virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0; - - virtual void end_frame(bool p_swap_buffers) = 0; - virtual void finalize() = 0; - virtual uint64_t get_frame_number() const = 0; - virtual float get_frame_delta_time() const = 0; - - virtual bool is_low_end() const = 0; - - virtual ~Rasterizer() {} -}; - -#endif // RASTERIZER_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h deleted file mode 100644 index db083a75cc..0000000000 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ /dev/null @@ -1,602 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_high_end_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 RASTERIZER_SCENE_HIGHEND_RD_H -#define RASTERIZER_SCENE_HIGHEND_RD_H - -#include "servers/rendering/rasterizer_rd/rasterizer_scene_rd.h" -#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" -#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" -#include "servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl.gen.h" - -class RasterizerSceneHighEndRD : public RasterizerSceneRD { - enum { - SCENE_UNIFORM_SET = 0, - RADIANCE_UNIFORM_SET = 1, - VIEW_DEPENDANT_UNIFORM_SET = 2, - RENDER_BUFFERS_UNIFORM_SET = 3, - TRANSFORMS_UNIFORM_SET = 4, - MATERIAL_UNIFORM_SET = 5 - }; - - enum { - SDFGI_MAX_CASCADES = 8, - MAX_GI_PROBES = 8 - }; - - /* Scene Shader */ - - enum ShaderVersion { - SHADER_VERSION_DEPTH_PASS, - SHADER_VERSION_DEPTH_PASS_DP, - SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, - SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, - SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, - SHADER_VERSION_DEPTH_PASS_WITH_SDF, - SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, - SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_MAX - }; - - struct { - SceneHighEndShaderRD scene_shader; - ShaderCompilerRD compiler; - } shader; - - RasterizerStorageRD *storage; - - /* Material */ - - struct ShaderData : public RasterizerStorageRD::ShaderData { - enum BlendMode { //used internally - BLEND_MODE_MIX, - BLEND_MODE_ADD, - BLEND_MODE_SUB, - BLEND_MODE_MUL, - BLEND_MODE_ALPHA_TO_COVERAGE - }; - - enum DepthDraw { - DEPTH_DRAW_DISABLED, - DEPTH_DRAW_OPAQUE, - DEPTH_DRAW_ALWAYS - }; - - enum DepthTest { - DEPTH_TEST_DISABLED, - DEPTH_TEST_ENABLED - }; - - enum Cull { - CULL_DISABLED, - CULL_FRONT, - CULL_BACK - }; - - enum CullVariant { - CULL_VARIANT_NORMAL, - CULL_VARIANT_REVERSED, - CULL_VARIANT_DOUBLE_SIDED, - CULL_VARIANT_MAX - - }; - - enum AlphaAntiAliasing { - ALPHA_ANTIALIASING_OFF, - ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE, - ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE - }; - - bool valid; - RID version; - uint32_t vertex_input_mask; - RenderPipelineVertexFormatCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; - - String path; - - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; - Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms; - - Vector<uint32_t> ubo_offsets; - uint32_t ubo_size; - - String code; - Map<StringName, RID> default_texture_params; - - DepthDraw depth_draw; - DepthTest depth_test; - - bool uses_point_size; - bool uses_alpha; - bool uses_blend_alpha; - bool uses_alpha_clip; - bool uses_depth_pre_pass; - bool uses_discard; - bool uses_roughness; - bool uses_normal; - - bool unshaded; - bool uses_vertex; - bool uses_sss; - bool uses_transmittance; - bool uses_screen_texture; - bool uses_depth_texture; - bool uses_normal_texture; - bool uses_time; - bool writes_modelview_or_projection; - bool uses_world_coordinates; - - uint64_t last_pass = 0; - uint32_t index = 0; - - virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - void get_instance_param_list(List<RasterizerStorage::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; - ShaderData(); - virtual ~ShaderData(); - }; - - RasterizerStorageRD::ShaderData *_create_shader_func(); - static RasterizerStorageRD::ShaderData *_create_shader_funcs() { - return static_cast<RasterizerSceneHighEndRD *>(singleton)->_create_shader_func(); - } - - struct MaterialData : public RasterizerStorageRD::MaterialData { - uint64_t last_frame; - ShaderData *shader_data; - RID uniform_buffer; - RID uniform_set; - Vector<RID> texture_cache; - Vector<uint8_t> ubo_data; - uint64_t last_pass = 0; - uint32_t index = 0; - RID next_pass; - uint8_t priority; - virtual void set_render_priority(int p_priority); - virtual void set_next_pass(RID p_pass); - virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~MaterialData(); - }; - - RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { - return static_cast<RasterizerSceneHighEndRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); - } - - /* Push Constant */ - - struct PushConstant { - uint32_t index; - uint32_t pad; - float bake_uv2_offset[2]; - }; - - /* Framebuffer */ - - struct RenderBufferDataHighEnd : public RenderBufferData { - //for rendering, may be MSAAd - - RID color; - RID depth; - RID specular; - RID normal_roughness_buffer; - RID giprobe_buffer; - - RID ambient_buffer; - RID reflection_buffer; - - RS::ViewportMSAA msaa; - RD::TextureSamples texture_samples; - - RID color_msaa; - RID depth_msaa; - RID specular_msaa; - RID normal_roughness_buffer_msaa; - RID roughness_buffer_msaa; - RID giprobe_buffer_msaa; - - RID depth_fb; - RID depth_normal_roughness_fb; - RID depth_normal_roughness_giprobe_fb; - RID color_fb; - RID color_specular_fb; - RID specular_only_fb; - int width, height; - - RID render_sdfgi_uniform_set; - void ensure_specular(); - void ensure_gi(); - void ensure_giprobe(); - void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa); - - RID uniform_set; - - ~RenderBufferDataHighEnd(); - }; - - virtual RenderBufferData *_create_render_buffer_data(); - void _allocate_normal_roughness_texture(RenderBufferDataHighEnd *rb); - - RID shadow_sampler; - RID render_base_uniform_set; - RID view_dependant_uniform_set; - - uint64_t lightmap_texture_array_version = 0xFFFFFFFF; - - virtual void _base_uniforms_changed(); - void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb); - virtual void _render_buffers_uniform_set_changed(RID p_render_buffers); - virtual RID _render_buffers_get_normal_texture(RID p_render_buffers); - virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers); - virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers); - - void _update_render_base_uniform_set(); - void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count); - void _update_render_buffers_uniform_set(RID p_render_buffers); - - struct LightmapData { - float normal_xform[12]; - }; - - struct LightmapCaptureData { - float sh[9 * 4]; - }; - - enum { - INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6, - INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7, - INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8, - INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9, - INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10, - INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11, - INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, - INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, - INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, - INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, - INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16, - INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7, - INSTANCE_DATA_FLAG_SKELETON = 1 << 19, - }; - - struct InstanceData { - float transform[16]; - float normal_transform[16]; - uint32_t flags; - uint32_t instance_uniforms_ofs; //instance_offset in instancing/skeleton buffer - uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap) - uint32_t mask; - float lightmap_uv_scale[4]; - }; - - struct SceneState { - struct UBO { - float projection_matrix[16]; - float inv_projection_matrix[16]; - - float camera_matrix[16]; - float inv_camera_matrix[16]; - - float viewport_size[2]; - float screen_pixel_size[2]; - - float directional_penumbra_shadow_kernel[128]; //32 vec4s - float directional_soft_shadow_kernel[128]; - float penumbra_shadow_kernel[128]; - float soft_shadow_kernel[128]; - - uint32_t directional_penumbra_shadow_samples; - uint32_t directional_soft_shadow_samples; - uint32_t penumbra_shadow_samples; - uint32_t soft_shadow_samples; - - float ambient_light_color_energy[4]; - - float ambient_color_sky_mix; - uint32_t use_ambient_light; - uint32_t use_ambient_cubemap; - uint32_t use_reflection_cubemap; - - float radiance_inverse_xform[12]; - - float shadow_atlas_pixel_size[2]; - float directional_shadow_pixel_size[2]; - - uint32_t directional_light_count; - float dual_paraboloid_side; - float z_far; - float z_near; - - uint32_t ssao_enabled; - float ssao_light_affect; - float ssao_ao_affect; - uint32_t roughness_limiter_enabled; - - float roughness_limiter_amount; - float roughness_limiter_limit; - uint32_t roughness_limiter_pad[2]; - - float ao_color[4]; - - float sdf_to_bounds[16]; - - int32_t sdf_offset[3]; - uint32_t material_uv2_mode; - - int32_t sdf_size[3]; - uint32_t gi_upscale_for_msaa; - - uint32_t volumetric_fog_enabled; - float volumetric_fog_inv_length; - float volumetric_fog_detail_spread; - uint32_t volumetric_fog_pad; - - // Fog - uint32_t fog_enabled; - float fog_density; - float fog_height; - float fog_height_density; - - float fog_light_color[3]; - float fog_sun_scatter; - - float fog_aerial_perspective; - - float time; - float reflection_multiplier; - - uint32_t pancake_shadows; - }; - - UBO ubo; - - RID uniform_buffer; - - LightmapData *lightmaps; - uint32_t max_lightmaps; - RID lightmap_buffer; - - LightmapCaptureData *lightmap_captures; - uint32_t max_lightmap_captures; - RID lightmap_capture_buffer; - - RID instance_buffer; - InstanceData *instances; - uint32_t max_instances; - - bool used_screen_texture = false; - bool used_normal_texture = false; - bool used_depth_texture = false; - bool used_sss = false; - uint32_t current_shader_index = 0; - uint32_t current_material_index = 0; - - } scene_state; - - /* Render List */ - - struct RenderList { - int max_elements; - - struct Element { - RasterizerScene::InstanceBase *instance; - MaterialData *material; - union { - struct { - //from least significant to most significant in sort, TODO: should be endian swapped on big endian - uint64_t geometry_index : 20; - uint64_t material_index : 15; - uint64_t shader_index : 12; - uint64_t uses_instancing : 1; - uint64_t uses_forward_gi : 1; - uint64_t uses_lightmap : 1; - uint64_t depth_layer : 4; - uint64_t priority : 8; - }; - - uint64_t sort_key; - }; - uint32_t surface_index; - }; - - Element *base_elements; - Element **elements; - - int element_count; - int alpha_element_count; - - void clear() { - element_count = 0; - alpha_element_count = 0; - } - - //should eventually be replaced by radix - - struct SortByKey { - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - return A->sort_key < B->sort_key; - } - }; - - void sort_by_key(bool p_alpha) { - SortArray<Element *, SortByKey> sorter; - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - struct SortByDepth { - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - return A->instance->depth < B->instance->depth; - } - }; - - void sort_by_depth(bool p_alpha) { //used for shadows - - SortArray<Element *, SortByDepth> sorter; - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - struct SortByReverseDepthAndPriority { - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - uint32_t layer_A = uint32_t(A->priority); - uint32_t layer_B = uint32_t(B->priority); - if (layer_A == layer_B) { - return A->instance->depth > B->instance->depth; - } else { - return layer_A < layer_B; - } - } - }; - - void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha - - SortArray<Element *, SortByReverseDepthAndPriority> sorter; - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - _FORCE_INLINE_ Element *add_element() { - if (element_count + alpha_element_count >= max_elements) { - return nullptr; - } - elements[element_count] = &base_elements[element_count]; - return elements[element_count++]; - } - - _FORCE_INLINE_ Element *add_alpha_element() { - if (element_count + alpha_element_count >= max_elements) { - return nullptr; - } - int idx = max_elements - alpha_element_count - 1; - elements[idx] = &base_elements[idx]; - alpha_element_count++; - return elements[idx]; - } - - void init() { - element_count = 0; - alpha_element_count = 0; - elements = memnew_arr(Element *, max_elements); - base_elements = memnew_arr(Element, max_elements); - for (int i = 0; i < max_elements; i++) { - elements[i] = &base_elements[i]; // assign elements - } - } - - RenderList() { - max_elements = 0; - } - - ~RenderList() { - memdelete_arr(elements); - memdelete_arr(base_elements); - } - }; - - RenderList render_list; - - static RasterizerSceneHighEndRD *singleton; - uint64_t render_pass; - double time; - RID default_shader; - RID default_material; - RID overdraw_material_shader; - RID overdraw_material; - RID wireframe_material_shader; - RID wireframe_material; - RID default_shader_rd; - RID default_shader_sdfgi_rd; - RID default_radiance_uniform_set; - RID default_render_buffers_uniform_set; - - RID default_vec4_xform_buffer; - RID default_vec4_xform_uniform_set; - - enum PassMode { - PASS_MODE_COLOR, - PASS_MODE_COLOR_SPECULAR, - PASS_MODE_COLOR_TRANSPARENT, - PASS_MODE_SHADOW, - PASS_MODE_SHADOW_DP, - PASS_MODE_DEPTH, - PASS_MODE_DEPTH_NORMAL_ROUGHNESS, - PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE, - PASS_MODE_DEPTH_MATERIAL, - PASS_MODE_SDF, - }; - - void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false); - void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform); - - void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false); - void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2()); - _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false); - _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false); - - void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi = false); - - Map<Size2i, RID> sdfgi_framebuffer_size_cache; - -protected: - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color); - virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &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); - virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); - virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); - virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture); - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count); - -public: - virtual void set_time(double p_time, double p_step); - - virtual bool free(RID p_rid); - - RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage); - ~RasterizerSceneHighEndRD(); -}; -#endif // RASTERIZER_SCENE_HIGHEND_RD_H diff --git a/servers/rendering/rasterizer_rd/shaders/ssao.glsl b/servers/rendering/rasterizer_rd/shaders/ssao.glsl deleted file mode 100644 index 346338181a..0000000000 --- a/servers/rendering/rasterizer_rd/shaders/ssao.glsl +++ /dev/null @@ -1,249 +0,0 @@ -#[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -#define TWO_PI 6.283185307179586476925286766559 - -#ifdef SSAO_QUALITY_HIGH -#define NUM_SAMPLES (20) -#endif - -#ifdef SSAO_QUALITY_ULTRA -#define NUM_SAMPLES (48) -#endif - -#ifdef SSAO_QUALITY_LOW -#define NUM_SAMPLES (8) -#endif - -#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) && !defined(SSAO_QUALITY_ULTRA) -#define NUM_SAMPLES (12) -#endif - -// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower -// miplevel to maintain reasonable spatial locality in the cache -// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing. -// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively -#define LOG_MAX_OFFSET (3) - -// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp -#define MAX_MIP_LEVEL (4) - -// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent -// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 - -const int ROTATIONS[] = int[]( - 1, 1, 2, 3, 2, 5, 2, 3, 2, - 3, 3, 5, 5, 3, 4, 7, 5, 5, 7, - 9, 8, 5, 5, 7, 7, 7, 8, 5, 8, - 11, 12, 7, 10, 13, 8, 11, 8, 7, 14, - 11, 11, 13, 12, 13, 19, 17, 13, 11, 18, - 19, 11, 11, 14, 17, 21, 15, 16, 17, 18, - 13, 17, 11, 17, 19, 18, 25, 18, 19, 19, - 29, 21, 19, 27, 31, 29, 21, 18, 17, 29, - 31, 31, 23, 18, 25, 26, 25, 23, 19, 34, - 19, 27, 21, 25, 39, 29, 17, 21, 27); - -//#define NUM_SPIRAL_TURNS (7) -const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1]; - -layout(set = 0, binding = 0) uniform sampler2D source_depth_mipmaps; -layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; - -#ifndef USE_HALF_SIZE -layout(set = 2, binding = 0) uniform sampler2D source_depth; -#endif - -layout(set = 3, binding = 0) uniform sampler2D source_normal; - -layout(push_constant, binding = 1, std430) uniform Params { - ivec2 screen_size; - float z_far; - float z_near; - - bool orthogonal; - float intensity_div_r6; - float radius; - float bias; - - vec4 proj_info; - vec2 pixel_size; - float proj_scale; - uint pad; -} -params; - -vec3 reconstructCSPosition(vec2 S, float z) { - if (params.orthogonal) { - return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z); - } else { - return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z); - } -} - -vec3 getPosition(ivec2 ssP) { - vec3 P; -#ifdef USE_HALF_SIZE - P.z = texelFetch(source_depth_mipmaps, ssP, 0).r; - P.z = -P.z; -#else - P.z = texelFetch(source_depth, ssP, 0).r; - - P.z = P.z * 2.0 - 1.0; - if (params.orthogonal) { - P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near)); - } - P.z = -P.z; -#endif - // Offset to pixel center - P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); - return P; -} - -/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ -vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) { - // Radius relative to ssR - float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES)); - float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle; - - ssR = alpha; - return vec2(cos(angle), sin(angle)); -} - -/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ -vec3 getOffsetPosition(ivec2 ssP, float ssR) { - // Derivation: - // mipLevel = floor(log(ssR / MAX_OFFSET)); - - int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); - - vec3 P; - - // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. - // Manually clamp to the texture size because texelFetch bypasses the texture unit - ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (params.screen_size >> mipLevel) - ivec2(1)); - -#ifdef USE_HALF_SIZE - P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel).r; - P.z = -P.z; -#else - if (mipLevel < 1) { - //read from depth buffer - P.z = texelFetch(source_depth, mipP, 0).r; - P.z = P.z * 2.0 - 1.0; - if (params.orthogonal) { - P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near)); - } - P.z = -P.z; - - } else { - //read from mipmaps - P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r; - P.z = -P.z; - } -#endif - - // Offset to pixel center - P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); - - return P; -} - -/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds - to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius - - Note that units of H() in the HPG12 paper are meters, not - unitless. The whole falloff/sampling function is therefore - unitless. In this implementation, we factor out (9 / radius). - - Four versions of the falloff function are implemented below -*/ -float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { - // Offset on the unit disk, spun for this pixel - float ssR; - vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); - ssR *= ssDiskRadius; - - ivec2 ssP = ivec2(ssR * unitOffset) + ssC; - - if (any(lessThan(ssP, ivec2(0))) || any(greaterThanEqual(ssP, params.screen_size))) { - return 0.0; - } - - // The occluding point in camera space - vec3 Q = getOffsetPosition(ssP, ssR); - - vec3 v = Q - C; - - float vv = dot(v, v); - float vn = dot(v, n_C); - - const float epsilon = 0.01; - float radius2 = p_radius * p_radius; - - // A: From the HPG12 paper - // Note large epsilon to avoid overdarkening within cracks - //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; - - // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] - float f = max(radius2 - vv, 0.0); - return f * f * f * max((vn - params.bias) / (epsilon + vv), 0.0); - - // C: Medium contrast (which looks better at high radii), no division. Note that the - // contribution still falls off with radius^2, but we've adjusted the rate in a way that is - // more computationally efficient and happens to be aesthetically pleasing. - // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); - - // D: Low contrast, no division operation - // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); -} - -void main() { - // Pixel being shaded - ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing - return; - } - - // World space point being shaded - vec3 C = getPosition(ssC); - -#ifdef USE_HALF_SIZE - vec3 n_C = texelFetch(source_normal, ssC << 1, 0).xyz * 2.0 - 1.0; -#else - vec3 n_C = texelFetch(source_normal, ssC, 0).xyz * 2.0 - 1.0; -#endif - n_C = normalize(n_C); - n_C.y = -n_C.y; //because this code reads flipped - - // Hash function used in the HPG12 AlchemyAO paper - float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI); - - // Reconstruct normals from positions. These will lead to 1-pixel black lines - // at depth discontinuities, however the blur will wipe those out so they are not visible - // in the final image. - - // Choose the screen-space sample radius - // proportional to the projected area of the sphere - - float ssDiskRadius = -params.proj_scale * params.radius; - if (!params.orthogonal) { - ssDiskRadius = -params.proj_scale * params.radius / C.z; - } - float sum = 0.0; - for (int i = 0; i < NUM_SAMPLES; ++i) { - sum += sampleAO(ssC, C, n_C, ssDiskRadius, params.radius, i, randomPatternRotationAngle); - } - - float A = max(0.0, 1.0 - sum * params.intensity_div_r6 * (5.0 / float(NUM_SAMPLES))); - - imageStore(dest_image, ssC, vec4(A)); -} diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl deleted file mode 100644 index 3e63e3cb59..0000000000 --- a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl +++ /dev/null @@ -1,153 +0,0 @@ -#[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -layout(set = 0, binding = 0) uniform sampler2D source_ssao; -layout(set = 1, binding = 0) uniform sampler2D source_depth; -#ifdef MODE_UPSCALE -layout(set = 2, binding = 0) uniform sampler2D source_depth_mipmaps; -#endif - -layout(r8, set = 3, binding = 0) uniform restrict writeonly image2D dest_image; - -////////////////////////////////////////////////////////////////////////////////////////////// -// Tunable Parameters: - -layout(push_constant, binding = 1, std430) uniform Params { - float edge_sharpness; /** Increase to make depth edges crisper. Decrease to reduce flicker. */ - int filter_scale; - float z_far; - float z_near; - bool orthogonal; - uint pad0; - uint pad1; - uint pad2; - ivec2 axis; /** (1, 0) or (0, 1) */ - ivec2 screen_size; -} -params; - -/** Filter radius in pixels. This will be multiplied by SCALE. */ -#define R (4) - -////////////////////////////////////////////////////////////////////////////////////////////// - -// Gaussian coefficients -const float gaussian[R + 1] = - //float[](0.356642, 0.239400, 0.072410, 0.009869); - //float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 - float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 -//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 - -void main() { - // Pixel being shaded - ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing - return; - } - -#ifdef MODE_UPSCALE - - //closest one should be the same pixel, but check nearby just in case - float depth = texelFetch(source_depth, ssC, 0).r; - - depth = depth * 2.0 - 1.0; - if (params.orthogonal) { - depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); - } - - vec2 pixel_size = 1.0 / vec2(params.screen_size); - vec2 closest_uv = vec2(ssC) * pixel_size + pixel_size * 0.5; - vec2 from_uv = closest_uv; - vec2 ps2 = pixel_size; // * 2.0; - - float closest_depth = abs(textureLod(source_depth_mipmaps, closest_uv, 0.0).r - depth); - - vec2 offsets[4] = vec2[](vec2(ps2.x, 0), vec2(-ps2.x, 0), vec2(0, ps2.y), vec2(0, -ps2.y)); - for (int i = 0; i < 4; i++) { - vec2 neighbour = from_uv + offsets[i]; - float neighbour_depth = abs(textureLod(source_depth_mipmaps, neighbour, 0.0).r - depth); - if (neighbour_depth < closest_depth) { - closest_uv = neighbour; - closest_depth = neighbour_depth; - } - } - - float visibility = textureLod(source_ssao, closest_uv, 0.0).r; - imageStore(dest_image, ssC, vec4(visibility)); -#else - - float depth = texelFetch(source_depth, ssC, 0).r; - -#ifdef MODE_FULL_SIZE - depth = depth * 2.0 - 1.0; - - if (params.orthogonal) { - depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); - } - -#endif - float depth_divide = 1.0 / params.z_far; - - //depth *= depth_divide; - - /* - if (depth > params.z_far * 0.999) { - discard; //skybox - } - */ - - float sum = texelFetch(source_ssao, ssC, 0).r; - - // Base weight for depth falloff. Increase this for more blurriness, - // decrease it for better edge discrimination - float BASE = gaussian[0]; - float totalWeight = BASE; - sum *= totalWeight; - - ivec2 clamp_limit = params.screen_size - ivec2(1); - - for (int r = -R; r <= R; ++r) { - // We already handled the zero case above. This loop should be unrolled and the static branch optimized out, - // so the IF statement has no runtime cost - if (r != 0) { - ivec2 ppos = ssC + params.axis * (r * params.filter_scale); - float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r; - ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit); - - float temp_depth = texelFetch(source_depth, rpos, 0).r; -#ifdef MODE_FULL_SIZE - temp_depth = temp_depth * 2.0 - 1.0; - if (params.orthogonal) { - temp_depth = ((temp_depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - temp_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - temp_depth * (params.z_far - params.z_near)); - } - //temp_depth *= depth_divide; -#endif - // spatial domain: offset gaussian tap - float weight = 0.3 + gaussian[abs(r)]; - //weight *= max(0.0, dot(temp_normal, normal)); - - // range domain (the "bilateral" weight). As depth difference increases, decrease weight. - weight *= max(0.0, 1.0 - params.edge_sharpness * abs(temp_depth - depth)); - - sum += value * weight; - totalWeight += weight; - } - } - - const float epsilon = 0.0001; - float visibility = sum / (totalWeight + epsilon); - - imageStore(dest_image, ssC, vec4(visibility)); -#endif -} diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl deleted file mode 100644 index 263fca386f..0000000000 --- a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl +++ /dev/null @@ -1,45 +0,0 @@ -#[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -layout(push_constant, binding = 1, std430) uniform Params { - vec2 pixel_size; - float z_far; - float z_near; - ivec2 source_size; - bool orthogonal; - uint pad; -} -params; - -#ifdef MINIFY_START -layout(set = 0, binding = 0) uniform sampler2D source_texture; -#else -layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_image; -#endif -layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; - -void main() { - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - - if (any(greaterThan(pos, params.source_size >> 1))) { //too large, do nothing - return; - } - -#ifdef MINIFY_START - float depth = texelFetch(source_texture, pos << 1, 0).r * 2.0 - 1.0; - if (params.orthogonal) { - depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); - } -#else - float depth = imageLoad(source_image, pos << 1).r; -#endif - - imageStore(dest_image, pos, vec4(depth)); -} diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/renderer_canvas_cull.cpp index ffc1ec391d..2d2847e6ca 100644 --- a/servers/rendering/rendering_server_canvas.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rendering_server_canvas.cpp */ +/* renderer_canvas_cull.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,20 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rendering_server_canvas.h" +#include "renderer_canvas_cull.h" #include "core/math/geometry_2d.h" +#include "renderer_viewport.h" +#include "rendering_server_default.h" #include "rendering_server_globals.h" -#include "rendering_server_raster.h" -#include "rendering_server_viewport.h" static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; -void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) { +void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) { RENDER_TIMESTAMP("Cull CanvasItem Tree"); - memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); - memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); + memset(z_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); + memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); for (int i = 0; i < p_child_item_count; i++) { _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr); @@ -50,8 +50,8 @@ void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Can _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr); } - RasterizerCanvas::Item *list = nullptr; - RasterizerCanvas::Item *list_end = nullptr; + RendererCanvasRender::Item *list = nullptr; + RendererCanvasRender::Item *list_end = nullptr; for (int i = 0; i < z_range; i++) { if (!z_list[i]) { @@ -75,9 +75,9 @@ void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Can } } -void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transform2D p_transform, RenderingServerCanvas::Item *p_material_owner, RenderingServerCanvas::Item **r_items, int &r_index) { +void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, RendererCanvasCull::Item **r_items, int &r_index) { int child_item_count = p_canvas_item->child_items.size(); - RenderingServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw(); + RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw(); for (int i = 0; i < child_item_count; i++) { if (child_items[i]->visible) { if (r_items) { @@ -97,14 +97,14 @@ void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transfo } } -void _mark_ysort_dirty(RenderingServerCanvas::Item *ysort_owner, RID_PtrOwner<RenderingServerCanvas::Item> &canvas_item_owner) { +void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<RendererCanvasCull::Item> &canvas_item_owner) { do { ysort_owner->ysort_children_count = -1; ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : nullptr; } while (ysort_owner && ysort_owner->sort_y); } -void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) { +void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) { Item *ci = p_canvas_item; if (!ci->visible) { @@ -144,7 +144,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo if (ci->clip) { if (p_canvas_clip != nullptr) { - ci->final_clip_rect = p_canvas_clip->final_clip_rect.clip(global_rect); + ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect); } else { ci->final_clip_rect = global_rect; } @@ -176,7 +176,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo p_z = ci->z_index; } - RasterizerCanvas::Item *canvas_group_from = nullptr; + RendererCanvasRender::Item *canvas_group_from = nullptr; bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr); if (use_canvas_group) { int zidx = p_z - RS::CANVAS_ITEM_Z_MIN; @@ -195,7 +195,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo } if (ci->copy_back_buffer) { - ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); + ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect); } if (use_canvas_group) { @@ -213,7 +213,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo //compute a global rect (in global coords) for children in the same z layer Rect2 rect_accum; - RasterizerCanvas::Item *c = canvas_group_from; + RendererCanvasRender::Item *c = canvas_group_from; while (c) { if (c == canvas_group_from) { rect_accum = c->global_rect_cache; @@ -227,7 +227,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo // We have two choices now, if user has drawn something, we must assume users wants to draw the "mask", so compute the size based on this. // If nothing has been drawn, we just take it over and draw it ourselves. if (ci->canvas_group->fit_empty && (ci->commands == nullptr || - (ci->commands->next == nullptr && ci->commands->type == Item::Command::TYPE_RECT && (static_cast<Item::CommandRect *>(ci->commands)->flags & RasterizerCanvas::CANVAS_RECT_IS_GROUP)))) { + (ci->commands->next == nullptr && ci->commands->type == Item::Command::TYPE_RECT && (static_cast<Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) { // No commands, or sole command is the one used to draw, so we (re)create the draw command. ci->clear(); @@ -238,9 +238,9 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo rect_accum = rect_accum.grow(ci->canvas_group->fit_margin); //draw it? - RasterizerCanvas::Item::CommandRect *crect = ci->alloc_command<RasterizerCanvas::Item::CommandRect>(); + RendererCanvasRender::Item::CommandRect *crect = ci->alloc_command<RendererCanvasRender::Item::CommandRect>(); - crect->flags = RasterizerCanvas::CANVAS_RECT_IS_GROUP; // so we can recognize it later + crect->flags = RendererCanvasRender::CANVAS_RECT_IS_GROUP; // so we can recognize it later crect->rect = xform.affine_inverse().xform(rect_accum); crect->modulate = Color(1, 1, 1, 1); @@ -256,14 +256,14 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo global_rect.position += p_clip_rect.position; } - // Very important that this is cleared after used in RasterizerCanvas to avoid + // Very important that this is cleared after used in RendererCanvasRender to avoid // potential crashes. canvas_group_from->canvas_group_owner = ci; } } if (ci->update_when_visible) { - RenderingServerRaster::redraw_request(); + RenderingServerDefault::redraw_request(); } if ((ci->commands != nullptr && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) { @@ -302,7 +302,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo } } -void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) { +void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) { RENDER_TIMESTAMP(">Render Canvas"); sdf_used = false; @@ -352,11 +352,11 @@ void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, RENDER_TIMESTAMP("<End Render Canvas"); } -bool RenderingServerCanvas::was_sdf_used() { +bool RendererCanvasCull::was_sdf_used() { return sdf_used; } -RID RenderingServerCanvas::canvas_create() { +RID RendererCanvasCull::canvas_create() { Canvas *canvas = memnew(Canvas); ERR_FAIL_COND_V(!canvas, RID()); RID rid = canvas_owner.make_rid(canvas); @@ -364,7 +364,7 @@ RID RenderingServerCanvas::canvas_create() { return rid; } -void RenderingServerCanvas::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) { +void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) { Canvas *canvas = canvas_owner.getornull(p_canvas); ERR_FAIL_COND(!canvas); Item *canvas_item = canvas_item_owner.getornull(p_item); @@ -375,17 +375,17 @@ void RenderingServerCanvas::canvas_set_item_mirroring(RID p_canvas, RID p_item, canvas->child_items.write[idx].mirror = p_mirroring; } -void RenderingServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color) { +void RendererCanvasCull::canvas_set_modulate(RID p_canvas, const Color &p_color) { Canvas *canvas = canvas_owner.getornull(p_canvas); ERR_FAIL_COND(!canvas); canvas->modulate = p_color; } -void RenderingServerCanvas::canvas_set_disable_scale(bool p_disable) { +void RendererCanvasCull::canvas_set_disable_scale(bool p_disable) { disable_scale = p_disable; } -void RenderingServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) { +void RendererCanvasCull::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) { Canvas *canvas = canvas_owner.getornull(p_canvas); ERR_FAIL_COND(!canvas); @@ -393,14 +393,14 @@ void RenderingServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float canvas->parent_scale = p_scale; } -RID RenderingServerCanvas::canvas_item_create() { +RID RendererCanvasCull::canvas_item_create() { Item *canvas_item = memnew(Item); ERR_FAIL_COND_V(!canvas_item, RID()); return canvas_item_owner.make_rid(canvas_item); } -void RenderingServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) { +void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -444,7 +444,7 @@ void RenderingServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) { canvas_item->parent = p_parent; } -void RenderingServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) { +void RendererCanvasCull::canvas_item_set_visible(RID p_item, bool p_visible) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -453,35 +453,35 @@ void RenderingServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) _mark_ysort_dirty(canvas_item, canvas_item_owner); } -void RenderingServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) { +void RendererCanvasCull::canvas_item_set_light_mask(RID p_item, int p_mask) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->light_mask = p_mask; } -void RenderingServerCanvas::canvas_item_set_transform(RID p_item, const Transform2D &p_transform) { +void RendererCanvasCull::canvas_item_set_transform(RID p_item, const Transform2D &p_transform) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->xform = p_transform; } -void RenderingServerCanvas::canvas_item_set_clip(RID p_item, bool p_clip) { +void RendererCanvasCull::canvas_item_set_clip(RID p_item, bool p_clip) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->clip = p_clip; } -void RenderingServerCanvas::canvas_item_set_distance_field_mode(RID p_item, bool p_enable) { +void RendererCanvasCull::canvas_item_set_distance_field_mode(RID p_item, bool p_enable) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->distance_field = p_enable; } -void RenderingServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect) { +void RendererCanvasCull::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -489,42 +489,42 @@ void RenderingServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custo canvas_item->rect = p_rect; } -void RenderingServerCanvas::canvas_item_set_modulate(RID p_item, const Color &p_color) { +void RendererCanvasCull::canvas_item_set_modulate(RID p_item, const Color &p_color) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->modulate = p_color; } -void RenderingServerCanvas::canvas_item_set_self_modulate(RID p_item, const Color &p_color) { +void RendererCanvasCull::canvas_item_set_self_modulate(RID p_item, const Color &p_color) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->self_modulate = p_color; } -void RenderingServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) { +void RendererCanvasCull::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->behind = p_enable; } -void RenderingServerCanvas::canvas_item_set_update_when_visible(RID p_item, bool p_update) { +void RendererCanvasCull::canvas_item_set_update_when_visible(RID p_item, bool p_update) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->update_when_visible = p_update; } -void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) { +void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>(); ERR_FAIL_COND(!line); if (p_width > 1.001) { - Vector2 t = (p_from - p_to).tangent().normalized(); + Vector2 t = (p_from - p_to).orthogonal().normalized(); line->points[0] = p_from + t * p_width; line->points[1] = p_from - t * p_width; line->points[2] = p_to - t * p_width; @@ -540,93 +540,146 @@ void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_fro } } -void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) { +void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { ERR_FAIL_COND(p_points.size() < 2); Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); + Color color = Color(1, 1, 1, 1); + + Vector<int> indices; + int pc = p_points.size(); + int pc2 = pc * 2; + + Vector2 prev_t; + int j2; + Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!pline); - if (true || p_width <= 1) { -#define TODO make thick lines possible - Vector<int> indices; - int pc = p_points.size(); - indices.resize((pc - 1) * 2); - { - int *iptr = indices.ptrw(); - for (int i = 0; i < (pc - 1); i++) { - iptr[i * 2 + 0] = i; - iptr[i * 2 + 1] = i + 1; - } - } + PackedColorArray colors; + PackedVector2Array points; - pline->primitive = RS::PRIMITIVE_LINES; - pline->polygon.create(indices, p_points, p_colors); - } else { -#if 0 - //make a trianglestrip for drawing the line... - Vector2 prev_t; - pline->triangles.resize(p_points.size() * 2); - if (p_antialiased) { - pline->lines.resize(p_points.size() * 2); - } + colors.resize(pc2); + points.resize(pc2); - if (p_colors.size() == 0) { - pline->triangle_colors.push_back(Color(1, 1, 1, 1)); - if (p_antialiased) { - pline->line_colors.push_back(Color(1, 1, 1, 1)); - } - } else if (p_colors.size() == 1) { - pline->triangle_colors = p_colors; - pline->line_colors = p_colors; - } else { - if (p_colors.size() != p_points.size()) { - pline->triangle_colors.push_back(p_colors[0]); - pline->line_colors.push_back(p_colors[0]); - } else { - pline->triangle_colors.resize(pline->triangles.size()); - pline->line_colors.resize(pline->lines.size()); - } - } + Vector2 *points_ptr = points.ptrw(); + Color *colors_ptr = colors.ptrw(); + + if (p_antialiased) { + Color color2 = Color(1, 1, 1, 0); + + PackedColorArray colors_top; + PackedVector2Array points_top; + + colors_top.resize(pc2); + points_top.resize(pc2); + + PackedColorArray colors_bottom; + PackedVector2Array points_bottom; + + colors_bottom.resize(pc2); + points_bottom.resize(pc2); + + Item::CommandPolygon *pline_top = canvas_item->alloc_command<Item::CommandPolygon>(); + ERR_FAIL_COND(!pline_top); + + Item::CommandPolygon *pline_bottom = canvas_item->alloc_command<Item::CommandPolygon>(); + ERR_FAIL_COND(!pline_bottom); + + //make three trianglestrip's for drawing the antialiased line... + + Vector2 *points_top_ptr = points_top.ptrw(); + Vector2 *points_bottom_ptr = points_bottom.ptrw(); + + Color *colors_top_ptr = colors_top.ptrw(); + Color *colors_bottom_ptr = colors_bottom.ptrw(); - for (int i = 0; i < p_points.size(); i++) { + for (int i = 0, j = 0; i < pc; i++, j += 2) { Vector2 t; - if (i == p_points.size() - 1) { + if (i == pc - 1) { t = prev_t; } else { - t = (p_points[i + 1] - p_points[i]).normalized().tangent(); + t = (p_points[i + 1] - p_points[i]).normalized().orthogonal(); if (i == 0) { prev_t = t; } } + j2 = j + 1; + Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5; + Vector2 pos = p_points[i]; + + points_ptr[j] = pos + tangent; + points_ptr[j2] = pos - tangent; + + points_top_ptr[j] = pos + tangent + tangent; + points_top_ptr[j2] = pos + tangent; + + points_bottom_ptr[j] = pos - tangent; + points_bottom_ptr[j2] = pos - tangent - tangent; + + if (i < p_colors.size()) { + color = p_colors[i]; + color2 = Color(color.r, color.g, color.b, 0); + } + + colors_ptr[j] = color; + colors_ptr[j2] = color; - if (p_antialiased) { - pline->lines.write[i] = p_points[i] + tangent; - pline->lines.write[p_points.size() * 2 - i - 1] = p_points[i] - tangent; - if (pline->line_colors.size() > 1) { - pline->line_colors.write[i] = p_colors[i]; - pline->line_colors.write[p_points.size() * 2 - i - 1] = p_colors[i]; + colors_top_ptr[j] = color2; + colors_top_ptr[j2] = color; + + colors_bottom_ptr[j] = color; + colors_bottom_ptr[j2] = color2; + + prev_t = t; + } + + pline_top->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + pline_top->polygon.create(indices, points_top, colors_top); + + pline_bottom->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + pline_bottom->polygon.create(indices, points_bottom, colors_bottom); + } else { + //make a trianglestrip for drawing the line... + + for (int i = 0, j = 0; i < pc; i++, j += 2) { + Vector2 t; + if (i == pc - 1) { + t = prev_t; + } else { + t = (p_points[i + 1] - p_points[i]).normalized().orthogonal(); + if (i == 0) { + prev_t = t; } } - pline->triangles.write[i * 2 + 0] = p_points[i] + tangent; - pline->triangles.write[i * 2 + 1] = p_points[i] - tangent; + j2 = j + 1; - if (pline->triangle_colors.size() > 1) { - pline->triangle_colors.write[i * 2 + 0] = p_colors[i]; - pline->triangle_colors.write[i * 2 + 1] = p_colors[i]; + Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5; + Vector2 pos = p_points[i]; + + points_ptr[j] = pos + tangent; + points_ptr[j2] = pos - tangent; + + if (i < p_colors.size()) { + color = p_colors[i]; } + colors_ptr[j] = color; + colors_ptr[j2] = color; + prev_t = t; } -#endif } + + pline->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; + pline->polygon.create(indices, points, colors); } -void RenderingServerCanvas::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) { +void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) { ERR_FAIL_COND(p_points.size() < 2); Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -643,7 +696,7 @@ void RenderingServerCanvas::canvas_item_add_multiline(RID p_item, const Vector<P } } -void RenderingServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) { +void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -653,7 +706,7 @@ void RenderingServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect rect->rect = p_rect; } -void RenderingServerCanvas::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) { +void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -687,7 +740,7 @@ void RenderingServerCanvas::canvas_item_add_circle(RID p_item, const Point2 &p_p circle->polygon.create(indices, points, color); } -void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) { +void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -697,28 +750,28 @@ void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 rect->rect = p_rect; rect->flags = 0; if (p_tile) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE; - rect->flags |= RasterizerCanvas::CANVAS_RECT_REGION; + rect->flags |= RendererCanvasRender::CANVAS_RECT_TILE; + rect->flags |= RendererCanvasRender::CANVAS_RECT_REGION; rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height)); } if (p_rect.size.x < 0) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H; rect->rect.size.x = -rect->rect.size.x; } if (p_rect.size.y < 0) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V; rect->rect.size.y = -rect->rect.size.y; } if (p_transpose) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + rect->flags |= RendererCanvasRender::CANVAS_RECT_TRANSPOSE; SWAP(rect->rect.size.x, rect->rect.size.y); } rect->texture = p_texture; } -void RenderingServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) { +void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -730,36 +783,36 @@ void RenderingServerCanvas::canvas_item_add_texture_rect_region(RID p_item, cons rect->texture = p_texture; rect->source = p_src_rect; - rect->flags = RasterizerCanvas::CANVAS_RECT_REGION; + rect->flags = RendererCanvasRender::CANVAS_RECT_REGION; if (p_rect.size.x < 0) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H; rect->rect.size.x = -rect->rect.size.x; } if (p_src_rect.size.x < 0) { - rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H; rect->source.size.x = -rect->source.size.x; } if (p_rect.size.y < 0) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V; rect->rect.size.y = -rect->rect.size.y; } if (p_src_rect.size.y < 0) { - rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V; rect->source.size.y = -rect->source.size.y; } if (p_transpose) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + rect->flags |= RendererCanvasRender::CANVAS_RECT_TRANSPOSE; SWAP(rect->rect.size.x, rect->rect.size.y); } if (p_clip_uv) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_CLIP_UV; + rect->flags |= RendererCanvasRender::CANVAS_RECT_CLIP_UV; } } -void RenderingServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode, RS::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate) { +void RendererCanvasCull::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode, RS::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -772,15 +825,15 @@ void RenderingServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2 & style->source = p_source; style->draw_center = p_draw_center; style->color = p_modulate; - style->margin[MARGIN_LEFT] = p_topleft.x; - style->margin[MARGIN_TOP] = p_topleft.y; - style->margin[MARGIN_RIGHT] = p_bottomright.x; - style->margin[MARGIN_BOTTOM] = p_bottomright.y; + style->margin[SIDE_LEFT] = p_topleft.x; + style->margin[SIDE_TOP] = p_topleft.y; + style->margin[SIDE_RIGHT] = p_bottomright.x; + style->margin[SIDE_BOTTOM] = p_bottomright.y; style->axis_x = p_x_axis_mode; style->axis_y = p_y_axis_mode; } -void RenderingServerCanvas::canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width) { +void RendererCanvasCull::canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width) { uint32_t pc = p_points.size(); ERR_FAIL_COND(pc == 0 || pc > 4); @@ -809,7 +862,7 @@ void RenderingServerCanvas::canvas_item_add_primitive(RID p_item, const Vector<P prim->texture = p_texture; } -void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture) { +void RendererCanvasCull::canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); #ifdef DEBUG_ENABLED @@ -821,7 +874,7 @@ void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Poi ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount)); #endif Vector<int> indices = Geometry2D::triangulate_polygon(p_points); - ERR_FAIL_COND_MSG(indices.empty(), "Invalid polygon data, triangulation failed."); + ERR_FAIL_COND_MSG(indices.is_empty(), "Invalid polygon data, triangulation failed."); Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!polygon); @@ -830,16 +883,16 @@ void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Poi polygon->polygon.create(indices, p_points, p_colors, p_uvs); } -void RenderingServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count) { +void RendererCanvasCull::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); int vertex_count = p_points.size(); ERR_FAIL_COND(vertex_count == 0); - ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != vertex_count && p_colors.size() != 1); - ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != vertex_count); - ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4); - ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4); + ERR_FAIL_COND(!p_colors.is_empty() && p_colors.size() != vertex_count && p_colors.size() != 1); + ERR_FAIL_COND(!p_uvs.is_empty() && p_uvs.size() != vertex_count); + ERR_FAIL_COND(!p_bones.is_empty() && p_bones.size() != vertex_count * 4); + ERR_FAIL_COND(!p_weights.is_empty() && p_weights.size() != vertex_count * 4); Vector<int> indices = p_indices; @@ -853,7 +906,7 @@ void RenderingServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vec polygon->primitive = RS::PRIMITIVE_TRIANGLES; } -void RenderingServerCanvas::canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) { +void RendererCanvasCull::canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -862,7 +915,7 @@ void RenderingServerCanvas::canvas_item_add_set_transform(RID p_item, const Tran tr->xform = p_transform; } -void RenderingServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture) { +void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -876,7 +929,7 @@ void RenderingServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, m->modulate = p_modulate; } -void RenderingServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture) { +void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -890,7 +943,7 @@ void RenderingServerCanvas::canvas_item_add_particles(RID p_item, RID p_particle RSG::storage->particles_request_process(p_particles); } -void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) { +void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -901,7 +954,7 @@ void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RI mm->texture = p_texture; } -void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) { +void RendererCanvasCull::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -910,7 +963,7 @@ void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignor ci->ignore = p_ignore; } -void RenderingServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { +void RendererCanvasCull::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -919,7 +972,7 @@ void RenderingServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool _mark_ysort_dirty(canvas_item, canvas_item_owner); } -void RenderingServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) { +void RendererCanvasCull::canvas_item_set_z_index(RID p_item, int p_z) { ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN || p_z > RS::CANVAS_ITEM_Z_MAX); Item *canvas_item = canvas_item_owner.getornull(p_item); @@ -928,25 +981,25 @@ void RenderingServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) { canvas_item->z_index = p_z; } -void RenderingServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { +void RendererCanvasCull::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->z_relative = p_enable; } -void RenderingServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) { +void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->skeleton = p_skeleton; } -void RenderingServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) { +void RendererCanvasCull::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); if (p_enable && (canvas_item->copy_back_buffer == nullptr)) { - canvas_item->copy_back_buffer = memnew(RasterizerCanvas::Item::CopyBackBuffer); + canvas_item->copy_back_buffer = memnew(RendererCanvasRender::Item::CopyBackBuffer); } if (!p_enable && (canvas_item->copy_back_buffer != nullptr)) { memdelete(canvas_item->copy_back_buffer); @@ -959,14 +1012,14 @@ void RenderingServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool } } -void RenderingServerCanvas::canvas_item_clear(RID p_item) { +void RendererCanvasCull::canvas_item_clear(RID p_item) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->clear(); } -void RenderingServerCanvas::canvas_item_set_draw_index(RID p_item, int p_index) { +void RendererCanvasCull::canvas_item_set_draw_index(RID p_item, int p_index) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -985,21 +1038,21 @@ void RenderingServerCanvas::canvas_item_set_draw_index(RID p_item, int p_index) } } -void RenderingServerCanvas::canvas_item_set_material(RID p_item, RID p_material) { +void RendererCanvasCull::canvas_item_set_material(RID p_item, RID p_material) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->material = p_material; } -void RenderingServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool p_enable) { +void RendererCanvasCull::canvas_item_set_use_parent_material(RID p_item, bool p_enable) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); canvas_item->use_parent_material = p_enable; } -void RenderingServerCanvas::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) { +void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -1010,7 +1063,7 @@ void RenderingServerCanvas::canvas_item_set_canvas_group_mode(RID p_item, RS::Ca } } else { if (canvas_item->canvas_group == nullptr) { - canvas_item->canvas_group = memnew(RasterizerCanvas::Item::CanvasGroup); + canvas_item->canvas_group = memnew(RendererCanvasRender::Item::CanvasGroup); } canvas_item->canvas_group->mode = p_mode; canvas_item->canvas_group->fit_empty = p_fit_empty; @@ -1020,14 +1073,14 @@ void RenderingServerCanvas::canvas_item_set_canvas_group_mode(RID p_item, RS::Ca } } -RID RenderingServerCanvas::canvas_light_create() { - RasterizerCanvas::Light *clight = memnew(RasterizerCanvas::Light); +RID RendererCanvasCull::canvas_light_create() { + RendererCanvasRender::Light *clight = memnew(RendererCanvasRender::Light); clight->light_internal = RSG::canvas_render->light_create(); return canvas_light_owner.make_rid(clight); } -void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); if (clight->mode == p_mode) { @@ -1047,8 +1100,8 @@ void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMo } } -void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); if (clight->canvas.is_valid()) { @@ -1076,29 +1129,29 @@ void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_can } } -void RenderingServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_enabled(RID p_light, bool p_enabled) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->enabled = p_enabled; } -void RenderingServerCanvas::canvas_light_set_texture_scale(RID p_light, float p_scale) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_texture_scale(RID p_light, float p_scale) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->scale = p_scale; } -void RenderingServerCanvas::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->xform = p_transform; } -void RenderingServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_texture(RID p_light, RID p_texture) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); if (clight->texture == p_texture) { @@ -1109,80 +1162,80 @@ void RenderingServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) RSG::canvas_render->light_set_texture(clight->light_internal, p_texture); } -void RenderingServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->texture_offset = p_offset; } -void RenderingServerCanvas::canvas_light_set_color(RID p_light, const Color &p_color) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_color(RID p_light, const Color &p_color) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->color = p_color; } -void RenderingServerCanvas::canvas_light_set_height(RID p_light, float p_height) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_height(RID p_light, float p_height) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->height = p_height; } -void RenderingServerCanvas::canvas_light_set_energy(RID p_light, float p_energy) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_energy(RID p_light, float p_energy) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->energy = p_energy; } -void RenderingServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->z_min = p_min_z; clight->z_max = p_max_z; } -void RenderingServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->layer_max = p_max_layer; clight->layer_min = p_min_layer; } -void RenderingServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_item_cull_mask(RID p_light, int p_mask) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->item_mask = p_mask; } -void RenderingServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->item_shadow_mask = p_mask; } -void RenderingServerCanvas::canvas_light_set_directional_distance(RID p_light, float p_distance) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_directional_distance(RID p_light, float p_distance) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->directional_distance = p_distance; } -void RenderingServerCanvas::canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->blend_mode = p_mode; } -void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); if (clight->use_shadow == p_enabled) { @@ -1193,34 +1246,34 @@ void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_ RSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow); } -void RenderingServerCanvas::canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->shadow_filter = p_filter; } -void RenderingServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color &p_color) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_shadow_color(RID p_light, const Color &p_color) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->shadow_color = p_color; } -void RenderingServerCanvas::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) { - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); +void RendererCanvasCull::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) { + RendererCanvasRender::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); clight->shadow_smooth = p_smooth; } -RID RenderingServerCanvas::canvas_light_occluder_create() { - RasterizerCanvas::LightOccluderInstance *occluder = memnew(RasterizerCanvas::LightOccluderInstance); +RID RendererCanvasCull::canvas_light_occluder_create() { + RendererCanvasRender::LightOccluderInstance *occluder = memnew(RendererCanvasRender::LightOccluderInstance); return canvas_light_occluder_owner.make_rid(occluder); } -void RenderingServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) { - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); +void RendererCanvasCull::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) { + RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); ERR_FAIL_COND(!occluder); if (occluder->canvas.is_valid()) { @@ -1240,15 +1293,15 @@ void RenderingServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occlude } } -void RenderingServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) { - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); +void RendererCanvasCull::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) { + RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); ERR_FAIL_COND(!occluder); occluder->enabled = p_enabled; } -void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) { - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); +void RendererCanvasCull::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) { + RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); ERR_FAIL_COND(!occluder); if (occluder->polygon.is_valid()) { @@ -1275,32 +1328,32 @@ void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RI } } -void RenderingServerCanvas::canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) { - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); +void RendererCanvasCull::canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) { + RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); ERR_FAIL_COND(!occluder); } -void RenderingServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) { - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); +void RendererCanvasCull::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) { + RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); ERR_FAIL_COND(!occluder); occluder->xform = p_xform; } -void RenderingServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) { - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); +void RendererCanvasCull::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) { + RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); ERR_FAIL_COND(!occluder); occluder->light_mask = p_mask; } -RID RenderingServerCanvas::canvas_occluder_polygon_create() { +RID RendererCanvasCull::canvas_occluder_polygon_create() { LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon); occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create(); return canvas_light_occluder_polygon_owner.make_rid(occluder_poly); } -void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) { +void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) { LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon); ERR_FAIL_COND(!occluder_poly); @@ -1319,66 +1372,66 @@ void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_pol RSG::canvas_render->occluder_polygon_set_shape(occluder_poly->occluder, p_shape, p_closed); - for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { + for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->aabb_cache = occluder_poly->aabb; } } -void RenderingServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode) { +void RendererCanvasCull::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode) { LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon); ERR_FAIL_COND(!occluder_poly); occluder_poly->cull_mode = p_mode; RSG::canvas_render->occluder_polygon_set_cull_mode(occluder_poly->occluder, p_mode); - for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { + for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = occluder_poly->owners.front(); E; E = E->next()) { E->get()->cull_cache = p_mode; } } -void RenderingServerCanvas::canvas_set_shadow_texture_size(int p_size) { +void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) { RSG::canvas_render->set_shadow_texture_size(p_size); } -RID RenderingServerCanvas::canvas_texture_create() { +RID RendererCanvasCull::canvas_texture_create() { return RSG::storage->canvas_texture_create(); } -void RenderingServerCanvas::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { +void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { RSG::storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture); } -void RenderingServerCanvas::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) { +void RendererCanvasCull::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) { RSG::storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess); } -void RenderingServerCanvas::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { +void RendererCanvasCull::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { RSG::storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter); } -void RenderingServerCanvas::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { +void RendererCanvasCull::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { RSG::storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat); } -void RenderingServerCanvas::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) { +void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) { Item *ci = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!ci); ci->texture_filter = p_filter; } -void RenderingServerCanvas::canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) { +void RendererCanvasCull::canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) { Item *ci = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!ci); ci->texture_repeat = p_repeat; } -bool RenderingServerCanvas::free(RID p_rid) { +bool RendererCanvasCull::free(RID p_rid) { if (canvas_owner.owns(p_rid)) { Canvas *canvas = canvas_owner.getornull(p_rid); ERR_FAIL_COND_V(!canvas, false); while (canvas->viewports.size()) { - RenderingServerViewport::Viewport *vp = RSG::viewport->viewport_owner.getornull(canvas->viewports.front()->get()); + RendererViewport::Viewport *vp = RSG::viewport->viewport_owner.getornull(canvas->viewports.front()->get()); ERR_FAIL_COND_V(!vp, true); - Map<RID, RenderingServerViewport::Viewport::CanvasData>::Element *E = vp->canvas_map.find(p_rid); + Map<RID, RendererViewport::Viewport::CanvasData>::Element *E = vp->canvas_map.find(p_rid); ERR_FAIL_COND_V(!E, true); vp->canvas_map.erase(p_rid); @@ -1389,11 +1442,11 @@ bool RenderingServerCanvas::free(RID p_rid) { canvas->child_items[i].item->parent = RID(); } - for (Set<RasterizerCanvas::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) { + for (Set<RendererCanvasRender::Light *>::Element *E = canvas->lights.front(); E; E = E->next()) { E->get()->canvas = RID(); } - for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) { + for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *E = canvas->occluders.front(); E; E = E->next()) { E->get()->canvas = RID(); } @@ -1434,7 +1487,7 @@ bool RenderingServerCanvas::free(RID p_rid) { memdelete(canvas_item); } else if (canvas_light_owner.owns(p_rid)) { - RasterizerCanvas::Light *canvas_light = canvas_light_owner.getornull(p_rid); + RendererCanvasRender::Light *canvas_light = canvas_light_owner.getornull(p_rid); ERR_FAIL_COND_V(!canvas_light, true); if (canvas_light->canvas.is_valid()) { @@ -1450,7 +1503,7 @@ bool RenderingServerCanvas::free(RID p_rid) { memdelete(canvas_light); } else if (canvas_light_occluder_owner.owns(p_rid)) { - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_rid); + RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_rid); ERR_FAIL_COND_V(!occluder, true); if (occluder->polygon.is_valid()) { @@ -1487,14 +1540,14 @@ bool RenderingServerCanvas::free(RID p_rid) { return true; } -RenderingServerCanvas::RenderingServerCanvas() { - z_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); - z_last_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); +RendererCanvasCull::RendererCanvasCull() { + z_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *)); + z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *)); disable_scale = false; } -RenderingServerCanvas::~RenderingServerCanvas() { +RendererCanvasCull::~RendererCanvasCull() { memfree(z_list); memfree(z_last_list); } diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/renderer_canvas_cull.h index 83b76539c4..7496a413ee 100644 --- a/servers/rendering/rendering_server_canvas.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rendering_server_canvas.h */ +/* renderer_canvas_cull.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSERVERCANVAS_H -#define VISUALSERVERCANVAS_H +#ifndef RENDERING_SERVER_CANVAS_CULL_H +#define RENDERING_SERVER_CANVAS_CULL_H -#include "rasterizer.h" -#include "rendering_server_viewport.h" +#include "renderer_compositor.h" +#include "renderer_viewport.h" -class RenderingServerCanvas { +class RendererCanvasCull { public: - struct Item : public RasterizerCanvas::Item { + struct Item : public RendererCanvasRender::Item { RID parent; // canvas it belongs to List<Item *>::Element *E; int z_index; @@ -93,7 +93,7 @@ public: Rect2 aabb; RS::CanvasOccluderPolygonCullMode cull_mode; RID occluder; - Set<RasterizerCanvas::LightOccluderInstance *> owners; + Set<RendererCanvasRender::LightOccluderInstance *> owners; LightOccluderPolygon() { active = false; @@ -103,9 +103,9 @@ public: RID_PtrOwner<LightOccluderPolygon> canvas_light_occluder_polygon_owner; - RID_PtrOwner<RasterizerCanvas::LightOccluderInstance> canvas_light_occluder_owner; + RID_PtrOwner<RendererCanvasRender::LightOccluderInstance> canvas_light_occluder_owner; - struct Canvas : public RenderingServerViewport::CanvasBase { + struct Canvas : public RendererViewport::CanvasBase { Set<RID> viewports; struct ChildItem { Point2 mirror; @@ -115,10 +115,10 @@ public: } }; - Set<RasterizerCanvas::Light *> lights; - Set<RasterizerCanvas::Light *> directional_lights; + Set<RendererCanvasRender::Light *> lights; + Set<RendererCanvasRender::Light *> directional_lights; - Set<RasterizerCanvas::LightOccluderInstance *> occluders; + Set<RendererCanvasRender::LightOccluderInstance *> occluders; bool children_order_dirty; Vector<ChildItem> child_items; @@ -150,21 +150,21 @@ public: mutable RID_PtrOwner<Canvas> canvas_owner; RID_PtrOwner<Item> canvas_item_owner; - RID_PtrOwner<RasterizerCanvas::Light> canvas_light_owner; + RID_PtrOwner<RendererCanvasRender::Light> canvas_light_owner; bool disable_scale; bool sdf_used = false; bool snapping_2d_transforms_to_pixel = false; private: - void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel); - void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner); + void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel); + void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner); - RasterizerCanvas::Item **z_list; - RasterizerCanvas::Item **z_last_list; + RendererCanvasRender::Item **z_list; + RendererCanvasRender::Item **z_last_list; public: - void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel); + void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel); bool was_sdf_used(); @@ -192,7 +192,7 @@ public: void canvas_item_set_update_when_visible(RID p_item, bool p_update); void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0); - void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0); + void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0); void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); @@ -272,8 +272,8 @@ public: void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat); bool free(RID p_rid); - RenderingServerCanvas(); - ~RenderingServerCanvas(); + RendererCanvasCull(); + ~RendererCanvasCull(); }; #endif // VISUALSERVERCANVAS_H diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp new file mode 100644 index 0000000000..1945435586 --- /dev/null +++ b/servers/rendering/renderer_canvas_render.cpp @@ -0,0 +1,31 @@ +/*************************************************************************/ +/* renderer_canvas_render.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#include "renderer_canvas_render.h" diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h new file mode 100644 index 0000000000..f08986b021 --- /dev/null +++ b/servers/rendering/renderer_canvas_render.h @@ -0,0 +1,604 @@ +/*************************************************************************/ +/* renderer_canvas_render.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RENDERINGSERVERCANVASRENDER_H +#define RENDERINGSERVERCANVASRENDER_H + +#include "servers/rendering/renderer_storage.h" + +class RendererCanvasRender { +public: + static RendererCanvasRender *singleton; + + enum CanvasRectFlags { + CANVAS_RECT_REGION = 1, + CANVAS_RECT_TILE = 2, + CANVAS_RECT_FLIP_H = 4, + CANVAS_RECT_FLIP_V = 8, + CANVAS_RECT_TRANSPOSE = 16, + CANVAS_RECT_CLIP_UV = 32, + CANVAS_RECT_IS_GROUP = 64, + }; + + struct Light { + bool enabled; + Color color; + Transform2D xform; + float height; + float energy; + float scale; + int z_min; + int z_max; + int layer_min; + int layer_max; + int item_mask; + int item_shadow_mask; + float directional_distance; + RS::CanvasLightMode mode; + RS::CanvasLightBlendMode blend_mode; + RID texture; + Vector2 texture_offset; + RID canvas; + bool use_shadow; + int shadow_buffer_size; + RS::CanvasLightShadowFilter shadow_filter; + Color shadow_color; + float shadow_smooth; + + //void *texture_cache; // implementation dependent + Rect2 rect_cache; + Transform2D xform_cache; + float radius_cache; //used for shadow far plane + //CameraMatrix shadow_matrix_cache; + + Transform2D light_shader_xform; + //Vector2 light_shader_pos; + + Light *shadows_next_ptr; + Light *filter_next_ptr; + Light *next_ptr; + Light *directional_next_ptr; + + RID light_internal; + uint64_t version; + + int32_t render_index_cache; + + Light() { + version = 0; + enabled = true; + color = Color(1, 1, 1); + shadow_color = Color(0, 0, 0, 0); + height = 0; + z_min = -1024; + z_max = 1024; + layer_min = 0; + layer_max = 0; + item_mask = 1; + scale = 1.0; + energy = 1.0; + item_shadow_mask = 1; + mode = RS::CANVAS_LIGHT_MODE_POINT; + blend_mode = RS::CANVAS_LIGHT_BLEND_MODE_ADD; + // texture_cache = nullptr; + next_ptr = nullptr; + directional_next_ptr = nullptr; + filter_next_ptr = nullptr; + use_shadow = false; + shadow_buffer_size = 2048; + shadow_filter = RS::CANVAS_LIGHT_FILTER_NONE; + shadow_smooth = 0.0; + render_index_cache = -1; + directional_distance = 10000.0; + } + }; + + //easier wrap to avoid mistakes + + struct Item; + + typedef uint64_t PolygonID; + virtual PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) = 0; + virtual void free_polygon(PolygonID p_polygon) = 0; + + //also easier to wrap to avoid mistakes + struct Polygon { + PolygonID polygon_id; + Rect2 rect_cache; + + _FORCE_INLINE_ void create(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) { + ERR_FAIL_COND(polygon_id != 0); + { + uint32_t pc = p_points.size(); + const Vector2 *v2 = p_points.ptr(); + rect_cache.position = *v2; + for (uint32_t i = 1; i < pc; i++) { + rect_cache.expand_to(v2[i]); + } + } + polygon_id = singleton->request_polygon(p_indices, p_points, p_colors, p_uvs, p_bones, p_weights); + } + + _FORCE_INLINE_ Polygon() { polygon_id = 0; } + _FORCE_INLINE_ ~Polygon() { + if (polygon_id) { + singleton->free_polygon(polygon_id); + } + } + }; + + //item + + struct Item { + //commands are allocated in blocks of 4k to improve performance + //and cache coherence. + //blocks always grow but never shrink. + + struct CommandBlock { + enum { + MAX_SIZE = 4096 + }; + uint32_t usage; + uint8_t *memory; + }; + + struct Command { + enum Type { + TYPE_RECT, + TYPE_NINEPATCH, + TYPE_POLYGON, + TYPE_PRIMITIVE, + TYPE_MESH, + TYPE_MULTIMESH, + TYPE_PARTICLES, + TYPE_TRANSFORM, + TYPE_CLIP_IGNORE, + }; + + Command *next; + Type type; + virtual ~Command() {} + }; + + struct CommandRect : public Command { + Rect2 rect; + Color modulate; + Rect2 source; + uint8_t flags; + + RID texture; + + CommandRect() { + flags = 0; + type = TYPE_RECT; + } + }; + + struct CommandNinePatch : public Command { + Rect2 rect; + Rect2 source; + float margin[4]; + bool draw_center; + Color color; + RS::NinePatchAxisMode axis_x; + RS::NinePatchAxisMode axis_y; + + RID texture; + + CommandNinePatch() { + draw_center = true; + type = TYPE_NINEPATCH; + } + }; + + struct CommandPolygon : public Command { + RS::PrimitiveType primitive; + Polygon polygon; + + RID texture; + + CommandPolygon() { + type = TYPE_POLYGON; + } + }; + + struct CommandPrimitive : public Command { + uint32_t point_count; + Vector2 points[4]; + Vector2 uvs[4]; + Color colors[4]; + + RID texture; + + CommandPrimitive() { + type = TYPE_PRIMITIVE; + } + }; + + struct CommandMesh : public Command { + RID mesh; + Transform2D transform; + Color modulate; + + RID texture; + + CommandMesh() { type = TYPE_MESH; } + }; + + struct CommandMultiMesh : public Command { + RID multimesh; + + RID texture; + + CommandMultiMesh() { type = TYPE_MULTIMESH; } + }; + + struct CommandParticles : public Command { + RID particles; + + RID texture; + + CommandParticles() { type = TYPE_PARTICLES; } + }; + + struct CommandTransform : public Command { + Transform2D xform; + CommandTransform() { type = TYPE_TRANSFORM; } + }; + + struct CommandClipIgnore : public Command { + bool ignore; + CommandClipIgnore() { + type = TYPE_CLIP_IGNORE; + ignore = false; + } + }; + + struct ViewportRender { + RenderingServer *owner; + void *udata; + Rect2 rect; + }; + + Transform2D xform; + bool clip; + bool visible; + bool behind; + bool update_when_visible; + + struct CanvasGroup { + RS::CanvasGroupMode mode; + bool fit_empty; + float fit_margin; + bool blur_mipmaps; + float clear_margin; + }; + + CanvasGroup *canvas_group = nullptr; + int light_mask; + int z_final; + + mutable bool custom_rect; + mutable bool rect_dirty; + mutable Rect2 rect; + RID material; + RID skeleton; + + Item *next; + + struct CopyBackBuffer { + Rect2 rect; + Rect2 screen_rect; + bool full; + }; + CopyBackBuffer *copy_back_buffer; + + Color final_modulate; + Transform2D final_transform; + Rect2 final_clip_rect; + Item *final_clip_owner; + Item *material_owner; + Item *canvas_group_owner; + ViewportRender *vp_render; + bool distance_field; + bool light_masked; + + Rect2 global_rect_cache; + + const Rect2 &get_rect() const { + if (custom_rect || (!rect_dirty && !update_when_visible)) { + return rect; + } + + //must update rect + + if (commands == nullptr) { + rect = Rect2(); + rect_dirty = false; + return rect; + } + + Transform2D xf; + bool found_xform = false; + bool first = true; + + const Item::Command *c = commands; + + while (c) { + Rect2 r; + + switch (c->type) { + case Item::Command::TYPE_RECT: { + const Item::CommandRect *crect = static_cast<const Item::CommandRect *>(c); + r = crect->rect; + + } break; + case Item::Command::TYPE_NINEPATCH: { + const Item::CommandNinePatch *style = static_cast<const Item::CommandNinePatch *>(c); + r = style->rect; + } break; + + case Item::Command::TYPE_POLYGON: { + const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c); + r = polygon->polygon.rect_cache; + } break; + case Item::Command::TYPE_PRIMITIVE: { + const Item::CommandPrimitive *primitive = static_cast<const Item::CommandPrimitive *>(c); + for (uint32_t j = 0; j < primitive->point_count; j++) { + if (j == 0) { + r.position = primitive->points[0]; + } else { + r.expand_to(primitive->points[j]); + } + } + } break; + case Item::Command::TYPE_MESH: { + const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c); + AABB aabb = RendererStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID()); + + r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + + } break; + case Item::Command::TYPE_MULTIMESH: { + const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c); + AABB aabb = RendererStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh); + + r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + + } break; + case Item::Command::TYPE_PARTICLES: { + const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c); + if (particles_cmd->particles.is_valid()) { + AABB aabb = RendererStorage::base_singleton->particles_get_aabb(particles_cmd->particles); + r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + } + + } break; + case Item::Command::TYPE_TRANSFORM: { + const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c); + xf = transform->xform; + found_xform = true; + [[fallthrough]]; + } + default: { + c = c->next; + continue; + } + } + + if (found_xform) { + r = xf.xform(r); + found_xform = false; + } + + if (first) { + rect = r; + first = false; + } else { + rect = rect.merge(r); + } + c = c->next; + } + + rect_dirty = false; + return rect; + } + + Command *commands; + Command *last_command; + Vector<CommandBlock> blocks; + uint32_t current_block; + + template <class T> + T *alloc_command() { + T *command; + if (commands == nullptr) { + // As the most common use case of canvas items is to + // use only one command, the first is done with it's + // own allocation. The rest of them use blocks. + command = memnew(T); + command->next = nullptr; + commands = command; + last_command = command; + } else { + //Subsequent commands go into a block. + + while (true) { + if (unlikely(current_block == (uint32_t)blocks.size())) { + // If we need more blocks, we allocate them + // (they won't be freed until this CanvasItem is + // deleted, though). + CommandBlock cb; + cb.memory = (uint8_t *)memalloc(CommandBlock::MAX_SIZE); + cb.usage = 0; + blocks.push_back(cb); + } + + CommandBlock *c = &blocks.write[current_block]; + size_t space_left = CommandBlock::MAX_SIZE - c->usage; + if (space_left < sizeof(T)) { + current_block++; + continue; + } + + //allocate block and add to the linked list + void *memory = c->memory + c->usage; + command = memnew_placement(memory, T); + command->next = nullptr; + last_command->next = command; + last_command = command; + c->usage += sizeof(T); + break; + } + } + + rect_dirty = true; + return command; + } + + void clear() { + // The first one is always allocated on heap + // the rest go in the blocks + Command *c = commands; + while (c) { + Command *n = c->next; + if (c == commands) { + memdelete(commands); + commands = nullptr; + } else { + c->~Command(); + } + c = n; + } + { + uint32_t cbc = MIN((current_block + 1), (uint32_t)blocks.size()); + CommandBlock *blockptr = blocks.ptrw(); + for (uint32_t i = 0; i < cbc; i++) { + blockptr[i].usage = 0; + } + } + + last_command = nullptr; + commands = nullptr; + current_block = 0; + clip = false; + rect_dirty = true; + final_clip_owner = nullptr; + material_owner = nullptr; + light_masked = false; + } + + RS::CanvasItemTextureFilter texture_filter; + RS::CanvasItemTextureRepeat texture_repeat; + + Item() { + commands = nullptr; + last_command = nullptr; + current_block = 0; + light_mask = 1; + vp_render = nullptr; + next = nullptr; + final_clip_owner = nullptr; + canvas_group_owner = nullptr; + clip = false; + final_modulate = Color(1, 1, 1, 1); + visible = true; + rect_dirty = true; + custom_rect = false; + behind = false; + material_owner = nullptr; + copy_back_buffer = nullptr; + distance_field = false; + light_masked = false; + update_when_visible = false; + z_final = 0; + texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + } + virtual ~Item() { + clear(); + for (int i = 0; i < blocks.size(); i++) { + memfree(blocks[i].memory); + } + if (copy_back_buffer) { + memdelete(copy_back_buffer); + } + } + }; + + virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) = 0; + virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0; + + struct LightOccluderInstance { + bool enabled; + RID canvas; + RID polygon; + RID occluder; + Rect2 aabb_cache; + Transform2D xform; + Transform2D xform_cache; + int light_mask; + bool sdf_collision; + RS::CanvasOccluderPolygonCullMode cull_cache; + + LightOccluderInstance *next; + + LightOccluderInstance() { + enabled = true; + sdf_collision = false; + next = nullptr; + light_mask = 1; + cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + } + }; + + virtual RID light_create() = 0; + virtual void light_set_texture(RID p_rid, RID p_texture) = 0; + virtual void light_set_use_shadow(RID p_rid, bool p_enable) = 0; + virtual void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0; + virtual void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) = 0; + + virtual void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) = 0; + + virtual RID occluder_polygon_create() = 0; + virtual void occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) = 0; + virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0; + virtual void set_shadow_texture_size(int p_size) = 0; + + virtual void draw_window_margins(int *p_margins, RID *p_margin_textures) = 0; + + virtual bool free(RID p_rid) = 0; + virtual void update() = 0; + + RendererCanvasRender() { singleton = this; } + virtual ~RendererCanvasRender() {} +}; + +#endif // RENDERINGSERVERCANVASRENDER_H diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp new file mode 100644 index 0000000000..8861522d34 --- /dev/null +++ b/servers/rendering/renderer_compositor.cpp @@ -0,0 +1,42 @@ +/*************************************************************************/ +/* renderer_compositor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#include "renderer_compositor.h" + +#include "core/os/os.h" +#include "core/string/print_string.h" + +RendererCompositor *(*RendererCompositor::_create_func)() = nullptr; + +RendererCompositor *RendererCompositor::create() { + return _create_func(); +} + +RendererCanvasRender *RendererCanvasRender::singleton = nullptr; diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h new file mode 100644 index 0000000000..919ae2c6da --- /dev/null +++ b/servers/rendering/renderer_compositor.h @@ -0,0 +1,78 @@ +/*************************************************************************/ +/* renderer_compositor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RENDERING_SERVER_COMPOSITOR_H +#define RENDERING_SERVER_COMPOSITOR_H + +#include "core/math/camera_matrix.h" +#include "core/templates/pair.h" +#include "core/templates/self_list.h" +#include "servers/rendering/renderer_canvas_render.h" +#include "servers/rendering/renderer_scene.h" +#include "servers/rendering/renderer_scene_render.h" +#include "servers/rendering/renderer_storage.h" +#include "servers/rendering_server.h" + +class RendererCompositor { +protected: + static RendererCompositor *(*_create_func)(); + +public: + static RendererCompositor *create(); + + virtual RendererStorage *get_storage() = 0; + virtual RendererCanvasRender *get_canvas() = 0; + virtual RendererSceneRender *get_scene() = 0; + + virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0; + + virtual void initialize() = 0; + virtual void begin_frame(double frame_step) = 0; + + struct BlitToScreen { + RID render_target; + Rect2i rect; + //lens distorted parameters for VR should go here + }; + + virtual void prepare_for_blitting_render_targets() = 0; + virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0; + + virtual void end_frame(bool p_swap_buffers) = 0; + virtual void finalize() = 0; + virtual uint64_t get_frame_number() const = 0; + virtual float get_frame_delta_time() const = 0; + + virtual bool is_low_end() const = 0; + + virtual ~RendererCompositor() {} +}; + +#endif // RASTERIZER_H diff --git a/servers/rendering/rasterizer_rd/SCsub b/servers/rendering/renderer_rd/SCsub index 6a2e682c67..6a2e682c67 100644 --- a/servers/rendering/rasterizer_rd/SCsub +++ b/servers/rendering/renderer_rd/SCsub diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index 97c1e7ba70..6e1d61ff94 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_effects_rd.cpp */ +/* effects_rd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,9 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rasterizer_effects_rd.h" +#include "effects_rd.h" #include "core/config/project_settings.h" +#include "core/math/math_defs.h" #include "core/os/os.h" #include "thirdparty/misc/cubemap_coeffs.h" @@ -58,7 +59,7 @@ static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_arra } } -RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) { +RID EffectsRD::_get_uniform_set_from_image(RID p_image) { if (image_to_uniform_set_cache.has(p_image)) { RID uniform_set = image_to_uniform_set_cache[p_image]; if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { @@ -67,7 +68,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) { } Vector<RD::Uniform> uniforms; RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; u.ids.push_back(p_image); uniforms.push_back(u); @@ -79,7 +80,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) { return uniform_set; } -RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { +RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { if (texture_to_uniform_set_cache.has(p_texture)) { RID uniform_set = texture_to_uniform_set_cache[p_texture]; if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { @@ -89,12 +90,12 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use Vector<RD::Uniform> uniforms; RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); u.ids.push_back(p_texture); uniforms.push_back(u); - //any thing with the same configuration (one texture in binding 0 for set 0), is good + //anything with the same configuration (one texture in binding 0 for set 0), is good RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, tonemap.shader.version_get_shader(tonemap.shader_version, 0), 0); texture_to_uniform_set_cache[p_texture] = uniform_set; @@ -102,7 +103,7 @@ RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use return uniform_set; } -RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { +RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { if (texture_to_compute_uniform_set_cache.has(p_texture)) { RID uniform_set = texture_to_compute_uniform_set_cache[p_texture]; if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { @@ -112,7 +113,7 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bo Vector<RD::Uniform> uniforms; RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); u.ids.push_back(p_texture); @@ -125,7 +126,34 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bo return uniform_set; } -RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) { +RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler) { + TextureSamplerPair tsp; + tsp.texture = p_texture; + tsp.sampler = p_sampler; + + if (texture_sampler_to_compute_uniform_set_cache.has(tsp)) { + RID uniform_set = texture_sampler_to_compute_uniform_set_cache[tsp]; + if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + return uniform_set; + } + } + + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.ids.push_back(p_sampler); + u.ids.push_back(p_texture); + uniforms.push_back(u); + //any thing with the same configuration (one texture in binding 0 for set 0), is good + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0), 0); + + texture_sampler_to_compute_uniform_set_cache[tsp] = uniform_set; + + return uniform_set; +} + +RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) { TexturePair tp; tp.texture1 = p_texture1; tp.texture2 = p_texture2; @@ -140,7 +168,7 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_textur Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); u.ids.push_back(p_texture1); @@ -148,7 +176,7 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_textur } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 1; u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); u.ids.push_back(p_texture2); @@ -162,7 +190,7 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_textur return uniform_set; } -RID RasterizerEffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_texture2) { +RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_texture2) { TexturePair tp; tp.texture1 = p_texture1; tp.texture2 = p_texture2; @@ -177,14 +205,14 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1 Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 0; u.ids.push_back(p_texture1); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(p_texture2); uniforms.push_back(u); @@ -197,7 +225,7 @@ RID RasterizerEffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1 return uniform_set; } -void RasterizerEffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) { +void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) { zeromem(©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); copy_to_fb.push_constant.use_section = true; @@ -218,7 +246,7 @@ void RasterizerEffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_f RD::get_singleton()->draw_list_draw(draw_list, true); } -void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary) { +void EffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary) { zeromem(©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); if (p_flip_y) { @@ -246,7 +274,7 @@ void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_fr RD::get_singleton()->draw_list_end(); } -void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) { +void EffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) { zeromem(©.push_constant, sizeof(CopyPushConstant)); if (p_flip_y) { copy.push_constant.flags |= COPY_FLAG_FLIP_Y; @@ -283,7 +311,7 @@ void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_textu RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) { +void EffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array) { zeromem(©.push_constant, sizeof(CopyPushConstant)); copy.push_constant.section[0] = 0; @@ -306,7 +334,7 @@ void RasterizerEffectsRD::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) { +void EffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far) { zeromem(©.push_constant, sizeof(CopyPushConstant)); if (p_flip_y) { copy.push_constant.flags |= COPY_FLAG_FLIP_Y; @@ -333,7 +361,7 @@ void RasterizerEffectsRD::copy_depth_to_rect_and_linearize(RID p_source_rd_textu RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) { +void EffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y) { zeromem(©.push_constant, sizeof(CopyPushConstant)); if (p_flip_y) { copy.push_constant.flags |= COPY_FLAG_FLIP_Y; @@ -358,7 +386,7 @@ void RasterizerEffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) { +void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) { zeromem(©.push_constant, sizeof(CopyPushConstant)); copy.push_constant.section[0] = 0; @@ -383,7 +411,7 @@ void RasterizerEffectsRD::set_color(RID p_dest_texture, const Color &p_color, co RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) { +void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) { zeromem(©.push_constant, sizeof(CopyPushConstant)); uint32_t base_flags = 0; @@ -418,7 +446,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { +void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { zeromem(©.push_constant, sizeof(CopyPushConstant)); CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW; @@ -455,7 +483,7 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_text RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { +void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); int32_t x_groups = (p_screen_size.width - 1) / 8 + 1; @@ -578,7 +606,7 @@ void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_ro RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { +void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); int32_t x_groups = (p_screen_size.width - 1) / 8 + 1; @@ -624,7 +652,7 @@ void RasterizerEffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, } } -void RasterizerEffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) { +void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>()); if (p_reflection.is_valid()) { @@ -654,7 +682,7 @@ void RasterizerEffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RD::get_singleton()->draw_list_end(); } -void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) { +void EffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) { zeromem(©.push_constant, sizeof(CopyPushConstant)); copy.push_constant.section[0] = 0; @@ -674,7 +702,7 @@ void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_textur RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) { +void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) { CopyToDPPushConstant push_constant; push_constant.screen_size[0] = p_rect.size.x; push_constant.screen_size[1] = p_rect.size.y; @@ -697,7 +725,7 @@ void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) { +void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) { zeromem(&tonemap.push_constant, sizeof(TonemapPushConstant)); tonemap.push_constant.use_bcs = p_settings.use_bcs; @@ -718,7 +746,10 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y; tonemap.push_constant.glow_mode = p_settings.glow_mode; - TonemapMode mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL; + int mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL; + if (p_settings.use_1d_color_correction) { + mode += 2; + } tonemap.push_constant.tonemapper = p_settings.tonemap_mode; tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure; @@ -746,7 +777,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, RD::get_singleton()->draw_list_end(); } -void RasterizerEffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { +void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { luminance_reduce.push_constant.source_size[0] = p_source_size.x; luminance_reduce.push_constant.source_size[1] = p_source_size.y; luminance_reduce.push_constant.max_luminance = p_max_luminance; @@ -788,7 +819,7 @@ void RasterizerEffectsRD::luminance_reduction(RID p_source_texture, const Size2i RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_halfsize_texture1, RID p_halfsize_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { +void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_halfsize_texture1, RID p_halfsize_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { bokeh.push_constant.blur_far_active = p_dof_far; bokeh.push_constant.blur_far_begin = p_dof_far_begin; bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; @@ -948,160 +979,348 @@ void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, con RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, RS::EnvironmentSSAOQuality p_quality, RS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness) { - //minify first - ssao.minify_push_constant.orthogonal = p_projection.is_orthogonal(); - ssao.minify_push_constant.z_near = p_projection.get_z_near(); - ssao.minify_push_constant.z_far = p_projection.get_z_far(); - ssao.minify_push_constant.pixel_size[0] = 1.0 / p_depth_buffer_size.x; - ssao.minify_push_constant.pixel_size[1] = 1.0 / p_depth_buffer_size.y; - ssao.minify_push_constant.source_size[0] = p_depth_buffer_size.x; - ssao.minify_push_constant.source_size[1] = p_depth_buffer_size.y; +void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass) { + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, ssao.gather_uniform_set, 0); + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) { + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, ssao.importance_map_uniform_set, 1); + } + + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + ssao.gather_push_constant.pass_coord_offset[0] = i % 2; + ssao.gather_push_constant.pass_coord_offset[1] = i / 2; + ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; + ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y; + ssao.gather_push_constant.pass = i; + RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2); + RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); + int x_groups = ((p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; + int y_groups = ((p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(p_compute_list, x_groups, y_groups, 1); + } + RD::get_singleton()->compute_list_add_barrier(p_compute_list); +} + +void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &p_depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); /* FIRST PASS */ - // Minify the depth buffer. - - for (int i = 0; i < depth_mipmaps.size(); i++) { - if (i == 0) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_FIRST]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0); - } else { - if (i == 1) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_MIPMAP]); + // Downsample and deinterleave the depth buffer. + { + if (p_invalidate_uniform_sets) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(p_depth_mipmaps[1]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(p_depth_mipmaps[2]); + uniforms.push_back(u); } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(p_depth_mipmaps[3]); + uniforms.push_back(u); + } + ssao.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, 2), 2); + } + + float depth_linearize_mul = -p_projection.matrix[3][2]; + float depth_linearize_add = p_projection.matrix[2][2]; + if (depth_linearize_mul * depth_linearize_add < 0) { + depth_linearize_add = -depth_linearize_add; + } + + ssao.downsample_push_constant.orthogonal = p_projection.is_orthogonal(); + ssao.downsample_push_constant.z_near = depth_linearize_mul; + ssao.downsample_push_constant.z_far = depth_linearize_add; + if (ssao.downsample_push_constant.orthogonal) { + ssao.downsample_push_constant.z_near = p_projection.get_z_near(); + ssao.downsample_push_constant.z_far = p_projection.get_z_far(); + } + ssao.downsample_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; + ssao.downsample_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; + ssao.downsample_push_constant.radius_sq = p_settings.radius * p_settings.radius; + + int downsample_pipeline = SSAO_DOWNSAMPLE; + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + downsample_pipeline = SSAO_DOWNSAMPLE_HALF; + } else if (p_settings.quality > RS::ENV_SSAO_QUALITY_MEDIUM) { + downsample_pipeline = SSAO_DOWNSAMPLE_MIPMAP; + } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[i - 1]), 0); + if (p_settings.half_size) { + downsample_pipeline++; } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[i]), 1); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.minify_push_constant, sizeof(SSAOMinifyPushConstant)); - // shrink after set - ssao.minify_push_constant.source_size[0] = MAX(1, ssao.minify_push_constant.source_size[0] >> 1); - ssao.minify_push_constant.source_size[1] = MAX(1, ssao.minify_push_constant.source_size[1] >> 1); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[downsample_pipeline]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[0]), 1); + if (p_settings.quality > RS::ENV_SSAO_QUALITY_MEDIUM) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.downsample_uniform_set, 2); + } + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.downsample_push_constant, sizeof(SSAODownsamplePushConstant)); - int x_groups = (ssao.minify_push_constant.source_size[0] - 1) / 8 + 1; - int y_groups = (ssao.minify_push_constant.source_size[1] - 1) / 8 + 1; + int x_groups = (MAX(1, p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; + int y_groups = (MAX(1, p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); RD::get_singleton()->compute_list_add_barrier(compute_list); } /* SECOND PASS */ - // Gather samples - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[(SSAO_GATHER_LOW + p_quality) + (p_half_size ? 4 : 0)]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 1); - if (!p_half_size) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 2); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_normal_buffer), 3); - - ssao.gather_push_constant.screen_size[0] = p_depth_buffer_size.x; - ssao.gather_push_constant.screen_size[1] = p_depth_buffer_size.y; - if (p_half_size) { - ssao.gather_push_constant.screen_size[0] >>= 1; - ssao.gather_push_constant.screen_size[1] >>= 1; - } - ssao.gather_push_constant.z_far = p_projection.get_z_far(); - ssao.gather_push_constant.z_near = p_projection.get_z_near(); - ssao.gather_push_constant.orthogonal = p_projection.is_orthogonal(); - - ssao.gather_push_constant.proj_info[0] = -2.0f / (ssao.gather_push_constant.screen_size[0] * p_projection.matrix[0][0]); - ssao.gather_push_constant.proj_info[1] = -2.0f / (ssao.gather_push_constant.screen_size[1] * p_projection.matrix[1][1]); - ssao.gather_push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; - ssao.gather_push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; - //ssao.gather_push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; - //ssao.gather_push_constant.proj_info[3] = -(1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; - - ssao.gather_push_constant.radius = p_radius; - - ssao.gather_push_constant.proj_scale = float(p_projection.get_pixels_per_meter(ssao.gather_push_constant.screen_size[0])); - ssao.gather_push_constant.bias = p_bias; - ssao.gather_push_constant.intensity_div_r6 = p_intensity / pow(p_radius, 6.0f); - - ssao.gather_push_constant.pixel_size[0] = 1.0 / p_depth_buffer_size.x; - ssao.gather_push_constant.pixel_size[1] = 1.0 / p_depth_buffer_size.y; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); + // Sample SSAO + { + ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; + ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y; + + ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; + ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; + float tan_half_fov_x = 1.0 / p_projection.matrix[0][0]; + float tan_half_fov_y = 1.0 / p_projection.matrix[1][1]; + ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0; + ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0; + ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0; + ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y; + ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal(); + + ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25; + ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25; + + float radius_near_limit = (p_settings.radius * 1.2f); + if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) { + radius_near_limit *= 1.50f; + + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + ssao.gather_push_constant.radius *= 0.8f; + } + if (p_settings.half_size) { + ssao.gather_push_constant.radius *= 0.5f; + } + } + radius_near_limit /= tan_half_fov_y; + ssao.gather_push_constant.radius = p_settings.radius; + ssao.gather_push_constant.intensity = p_settings.intensity; + ssao.gather_push_constant.shadow_power = p_settings.power; + ssao.gather_push_constant.shadow_clamp = 0.98; + ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from); + ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0; + ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon; + ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit; + ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius; + + ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255); + ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target; + + ssao.gather_push_constant.detail_intensity = p_settings.detail; + ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1); + ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1; + + if (p_invalidate_uniform_sets) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.ids.push_back(ssao.mirror_sampler); + u.ids.push_back(p_depth_mipmaps_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(p_normal_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.ids.push_back(ssao.gather_constants_buffer); + uniforms.push_back(u); + } + ssao.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0); + } - int x_groups = (ssao.gather_push_constant.screen_size[0] - 1) / 8 + 1; - int y_groups = (ssao.gather_push_constant.screen_size[1] - 1) / 8 + 1; + if (p_invalidate_uniform_sets) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(p_ao_pong); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 1; + u.ids.push_back(default_sampler); + u.ids.push_back(p_importance_map); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.ids.push_back(ssao.importance_map_load_counter); + uniforms.push_back(u); + } + ssao.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1); + } - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); + if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) { + ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; + ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; + ssao.importance_map_push_constant.intensity = p_settings.intensity; + ssao.importance_map_push_constant.power = p_settings.power; + //base pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]); + gather_ssao(compute_list, p_ao_pong_slices, p_settings, true); + //generate importance map + int x_groups = (p_settings.quarter_screen_size.x - 1) / 8 + 1; + int y_groups = (p_settings.quarter_screen_size.y - 1) / 8 + 1; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + //process importance map A + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + //process Importance Map B + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); - /* THIRD PASS */ - // Blur horizontal - - ssao.blur_push_constant.edge_sharpness = p_edge_sharpness; - ssao.blur_push_constant.filter_scale = p_blur; - ssao.blur_push_constant.screen_size[0] = ssao.gather_push_constant.screen_size[0]; - ssao.blur_push_constant.screen_size[1] = ssao.gather_push_constant.screen_size[1]; - ssao.blur_push_constant.z_far = p_projection.get_z_far(); - ssao.blur_push_constant.z_near = p_projection.get_z_near(); - ssao.blur_push_constant.orthogonal = p_projection.is_orthogonal(); - ssao.blur_push_constant.axis[0] = 1; - ssao.blur_push_constant.axis[1] = 0; - - if (p_blur != RS::ENV_SSAO_BLUR_DISABLED) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[p_half_size ? SSAO_BLUR_PASS_HALF : SSAO_BLUR_PASS]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0); - if (p_half_size) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 1); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]); } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]); } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao2), 3); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - /* THIRD PASS */ - // Blur vertical - - ssao.blur_push_constant.axis[0] = 0; - ssao.blur_push_constant.axis[1] = 1; + gather_ssao(compute_list, p_ao_slices, p_settings, false); + } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao2), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 3); + // /* THIRD PASS */ + // // Blur + // + { + ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness; + ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x; + ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; + + int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1; + + for (int pass = 0; pass < blur_passes; pass++) { + int blur_pipeline = SSAO_BLUR_PASS; + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { + if (pass < blur_passes - 2) { + blur_pipeline = SSAO_BLUR_PASS_WIDE; + } + blur_pipeline = SSAO_BLUR_PASS_SMART; + } - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); + for (int i = 0; i < 4; i++) { + if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) { + continue; + } + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]); + if (pass % 2 == 0) { + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_slices[i]), 0); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_slices[i], ssao.mirror_sampler), 0); + } + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_pong_slices[i]), 1); + } else { + if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong_slices[i]), 0); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_pong_slices[i], ssao.mirror_sampler), 0); + } + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 1); + } + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); + + int x_groups = ((p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; + int y_groups = ((p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + } - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) { + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + } } - if (p_half_size) { //must upscale - /* FOURTH PASS */ - // upscale if half size - //back to full size - ssao.blur_push_constant.screen_size[0] = p_depth_buffer_size.x; - ssao.blur_push_constant.screen_size[1] = p_depth_buffer_size.y; + /* FOURTH PASS */ + // Interleave buffers + // back to full size + { + ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; + ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; + ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y; + ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2); + + int interleave_pipeline = SSAO_INTERLEAVE_HALF; + if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) { + interleave_pipeline = SSAO_INTERLEAVE; + } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) { + interleave_pipeline = SSAO_INTERLEAVE_SMART; + } - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_BLUR_UPSCALE]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 3); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 2); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 0); + if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao), 1); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 1); + } - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); //not used but set anyway + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant)); - x_groups = (p_depth_buffer_size.x - 1) / 8 + 1; - y_groups = (p_depth_buffer_size.y - 1) / 8 + 1; + int x_groups = (p_settings.full_screen_size.x - 1) / 8 + 1; + int y_groups = (p_settings.full_screen_size.y - 1) / 8 + 1; RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); } RD::get_singleton()->compute_list_end(); + + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, false); } -void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) { +void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) { roughness_limiter.push_constant.screen_size[0] = p_size.x; roughness_limiter.push_constant.screen_size[1] = p_size.y; roughness_limiter.push_constant.curve = p_curve; @@ -1121,7 +1340,7 @@ void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) { +void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) { zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id; @@ -1146,7 +1365,7 @@ void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_ RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) { +void EffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) { cubemap_downsampler.push_constant.face_size = p_size.x; RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -1164,11 +1383,11 @@ void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cu RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) { +void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) { Vector<RD::Uniform> uniforms; for (int i = 0; i < p_dest_cubemap.size(); i++) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = i; u.ids.push_back(p_dest_cubemap[i]); uniforms.push_back(u); @@ -1193,7 +1412,7 @@ void RasterizerEffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_des RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) { +void EffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) { SkyPushConstant sky_push_constant; zeromem(&sky_push_constant, sizeof(SkyPushConstant)); @@ -1229,7 +1448,7 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_ RD::get_singleton()->draw_list_draw(draw_list, true); } -void RasterizerEffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples) { +void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples) { ResolvePushConstant push_constant; push_constant.screen_size[0] = p_screen_size.x; push_constant.screen_size[1] = p_screen_size.y; @@ -1251,7 +1470,7 @@ void RasterizerEffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_rou RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::reduce_shadow(RID p_source_shadow, RID p_dest_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, int p_shrink_limit, RD::ComputeListID compute_list) { +void EffectsRD::reduce_shadow(RID p_source_shadow, RID p_dest_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, int p_shrink_limit, RD::ComputeListID compute_list) { uint32_t push_constant[8] = { (uint32_t)p_source_size.x, (uint32_t)p_source_size.y, (uint32_t)p_source_rect.position.x, (uint32_t)p_source_rect.position.y, (uint32_t)p_shrink_limit, 0, 0, 0 }; RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shadow_reduce.pipelines[SHADOW_REDUCE_REDUCE]); @@ -1260,7 +1479,7 @@ void RasterizerEffectsRD::reduce_shadow(RID p_source_shadow, RID p_dest_shadow, RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_source_rect.size.width, p_source_rect.size.height, 1, 8, 8, 1); } -void RasterizerEffectsRD::filter_shadow(RID p_shadow, RID p_backing_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, RenderingServer::EnvVolumetricFogShadowFilter p_filter, RD::ComputeListID compute_list, bool p_vertical, bool p_horizontal) { +void EffectsRD::filter_shadow(RID p_shadow, RID p_backing_shadow, const Size2i &p_source_size, const Rect2i &p_source_rect, RenderingServer::EnvVolumetricFogShadowFilter p_filter, RD::ComputeListID compute_list, bool p_vertical, bool p_horizontal) { uint32_t push_constant[8] = { (uint32_t)p_source_size.x, (uint32_t)p_source_size.y, (uint32_t)p_source_rect.position.x, (uint32_t)p_source_rect.position.y, 0, 0, 0, 0 }; switch (p_filter) { @@ -1296,7 +1515,7 @@ void RasterizerEffectsRD::filter_shadow(RID p_shadow, RID p_backing_shadow, cons } } -void RasterizerEffectsRD::sort_buffer(RID p_uniform_set, int p_size) { +void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) { Sort::PushConstant push_constant; push_constant.total_elements = p_size; @@ -1365,7 +1584,7 @@ void RasterizerEffectsRD::sort_buffer(RID p_uniform_set, int p_size) { RD::get_singleton()->compute_list_end(); } -RasterizerEffectsRD::RasterizerEffectsRD() { +EffectsRD::EffectsRD() { { // Initialize copy Vector<String> copy_modes; copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); @@ -1423,6 +1642,8 @@ RasterizerEffectsRD::RasterizerEffectsRD() { Vector<String> tonemap_modes; tonemap_modes.push_back("\n"); tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n"); + tonemap_modes.push_back("\n#define USE_1D_LUT\n"); + tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n#define USE_1D_LUT\n"); tonemap.shader.initialize(tonemap_modes); @@ -1481,57 +1702,142 @@ RasterizerEffectsRD::RasterizerEffectsRD() { { // Initialize ssao + + RD::SamplerState sampler; + sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST; + sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler.max_lod = 4; + + ssao.mirror_sampler = RD::get_singleton()->sampler_create(sampler); + uint32_t pipeline = 0; { Vector<String> ssao_modes; - ssao_modes.push_back("\n#define MINIFY_START\n"); ssao_modes.push_back("\n"); + ssao_modes.push_back("\n#define USE_HALF_SIZE\n"); + ssao_modes.push_back("\n#define GENERATE_MIPS\n"); + ssao_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE"); + ssao_modes.push_back("\n#define USE_HALF_BUFFERS\n"); + ssao_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE"); - ssao.minify_shader.initialize(ssao_modes); + ssao.downsample_shader.initialize(ssao_modes); - ssao.minify_shader_version = ssao.minify_shader.version_create(); + ssao.downsample_shader_version = ssao.downsample_shader.version_create(); - for (int i = 0; i <= SSAO_MINIFY_MIPMAP; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.minify_shader.version_get_shader(ssao.minify_shader_version, i)); + for (int i = 0; i <= SSAO_DOWNSAMPLE_HALF_RES_HALF; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, i)); pipeline++; } } { Vector<String> ssao_modes; - ssao_modes.push_back("\n#define SSAO_QUALITY_LOW\n"); + ssao_modes.push_back("\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_HIGH\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_ULTRA\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_LOW\n#define USE_HALF_SIZE\n"); - ssao_modes.push_back("\n#define USE_HALF_SIZE\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_HIGH\n#define USE_HALF_SIZE\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_ULTRA\n#define USE_HALF_SIZE\n"); + ssao_modes.push_back("\n#define SSAO_BASE\n"); + ssao_modes.push_back("\n#define ADAPTIVE\n"); ssao.gather_shader.initialize(ssao_modes); ssao.gather_shader_version = ssao.gather_shader.version_create(); - for (int i = SSAO_GATHER_LOW; i <= SSAO_GATHER_ULTRA_HALF; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i - SSAO_GATHER_LOW)); + for (int i = SSAO_GATHER; i <= SSAO_GATHER_ADAPTIVE; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i - SSAO_GATHER)); pipeline++; } + + ssao.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSAOGatherConstants)); + SSAOGatherConstants gather_constants; + + const int sub_pass_count = 5; + for (int pass = 0; pass < 4; pass++) { + for (int subPass = 0; subPass < sub_pass_count; subPass++) { + int a = pass; + int b = subPass; + + int spmap[5]{ 0, 1, 4, 3, 2 }; + b = spmap[subPass]; + + float ca, sa; + float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f; + + ca = Math::cos(angle0); + sa = Math::sin(angle0); + + float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f; + + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa; + gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca; + } + } + + RD::get_singleton()->buffer_update(ssao.gather_constants_buffer, 0, sizeof(SSAOGatherConstants), &gather_constants, false); } { Vector<String> ssao_modes; - ssao_modes.push_back("\n#define MODE_FULL_SIZE\n"); - ssao_modes.push_back("\n"); - ssao_modes.push_back("\n#define MODE_UPSCALE\n"); + ssao_modes.push_back("\n#define GENERATE_MAP\n"); + ssao_modes.push_back("\n#define PROCESS_MAPA\n"); + ssao_modes.push_back("\n#define PROCESS_MAPB\n"); + + ssao.importance_map_shader.initialize(ssao_modes); + + ssao.importance_map_shader_version = ssao.importance_map_shader.version_create(); + + for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP)); + + pipeline++; + } + ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t)); + int zero[1] = { 0 }; + RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, false); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(ssao.importance_map_load_counter); + uniforms.push_back(u); + } + ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2); + } + { + Vector<String> ssao_modes; + ssao_modes.push_back("\n#define MODE_NON_SMART\n"); + ssao_modes.push_back("\n#define MODE_SMART\n"); + ssao_modes.push_back("\n#define MODE_WIDE\n"); ssao.blur_shader.initialize(ssao_modes); ssao.blur_shader_version = ssao.blur_shader.version_create(); - for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_UPSCALE; i++) { + for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) { ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS)); pipeline++; } } + { + Vector<String> ssao_modes; + ssao_modes.push_back("\n#define MODE_NON_SMART\n"); + ssao_modes.push_back("\n#define MODE_SMART\n"); + ssao_modes.push_back("\n#define MODE_HALF\n"); + + ssao.interleave_shader.initialize(ssao_modes); + + ssao.interleave_shader_version = ssao.interleave_shader.version_create(); + for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE)); + + pipeline++; + } + } ERR_FAIL_COND(pipeline != SSAO_MAX); } @@ -1586,7 +1892,7 @@ RasterizerEffectsRD::RasterizerEffectsRD() { Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; u.ids.push_back(filter.coefficient_buffer); uniforms.push_back(u); @@ -1758,7 +2064,7 @@ RasterizerEffectsRD::RasterizerEffectsRD() { } } -RasterizerEffectsRD::~RasterizerEffectsRD() { +EffectsRD::~EffectsRD() { if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { RD::get_singleton()->free(filter.image_uniform_set); } @@ -1772,6 +2078,10 @@ RasterizerEffectsRD::~RasterizerEffectsRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency RD::get_singleton()->free(filter.coefficient_buffer); + RD::get_singleton()->free(ssao.mirror_sampler); + RD::get_singleton()->free(ssao.gather_constants_buffer); + RD::get_singleton()->free(ssao.importance_map_load_counter); + bokeh.shader.version_free(bokeh.shader_version); copy.shader.version_free(copy.shader_version); copy_to_fb.shader.version_free(copy_to_fb.shader_version); @@ -1786,7 +2096,9 @@ RasterizerEffectsRD::~RasterizerEffectsRD() { specular_merge.shader.version_free(specular_merge.shader_version); ssao.blur_shader.version_free(ssao.blur_shader_version); ssao.gather_shader.version_free(ssao.gather_shader_version); - ssao.minify_shader.version_free(ssao.minify_shader_version); + ssao.downsample_shader.version_free(ssao.downsample_shader_version); + ssao.interleave_shader.version_free(ssao.interleave_shader_version); + ssao.importance_map_shader.version_free(ssao.importance_map_shader_version); ssr.shader.version_free(ssr.shader_version); ssr_filter.shader.version_free(ssr_filter.shader_version); ssr_scale.shader.version_free(ssr_scale.shader_version); diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index a0bdd59fd2..e2cdd0c3d8 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_effects_rd.h */ +/* effects_rd.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,36 +28,38 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_EFFECTS_RD_H -#define RASTERIZER_EFFECTS_RD_H +#ifndef EFFECTS_RD_H +#define EFFECTS_RD_H #include "core/math/camera_matrix.h" -#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" -#include "servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/copy.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/resolve.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/shadow_reduce.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/sort.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/specular_merge.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/ssao.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/tonemap.glsl.gen.h" +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/bokeh_dof.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/copy.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/cubemap_filter.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/shadow_reduce.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/specular_merge.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/ssao.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/ssao_blur.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/ssao_downsample.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/tonemap.glsl.gen.h" #include "servers/rendering_server.h" -class RasterizerEffectsRD { +class EffectsRD { enum CopyMode { COPY_MODE_GAUSSIAN_COPY, COPY_MODE_GAUSSIAN_COPY_8BIT, @@ -144,7 +146,7 @@ class RasterizerEffectsRD { CopyToFbPushConstant push_constant; CopyToFbShaderRD shader; RID shader_version; - RenderPipelineVertexFormatCacheRD pipelines[COPY_TO_FB_MAX]; + PipelineCacheRD pipelines[COPY_TO_FB_MAX]; } copy_to_fb; @@ -167,6 +169,8 @@ class RasterizerEffectsRD { enum TonemapMode { TONEMAP_MODE_NORMAL, TONEMAP_MODE_BICUBIC_GLOW_FILTER, + TONEMAP_MODE_1D_LUT, + TONEMAP_MODE_BICUBIC_GLOW_FILTER_1D_LUT, TONEMAP_MODE_MAX }; @@ -198,13 +202,13 @@ class RasterizerEffectsRD { /* tonemap actually writes to a framebuffer, which is * better to do using the raster pipeline rather than - * comptute, as that framebuffer might be in different formats + * compute, as that framebuffer might be in different formats */ struct Tonemap { TonemapPushConstant push_constant; TonemapShaderRD shader; RID shader_version; - RenderPipelineVertexFormatCacheRD pipelines[TONEMAP_MODE_MAX]; + PipelineCacheRD pipelines[TONEMAP_MODE_MAX]; } tonemap; enum LuminanceReduceMode { @@ -286,71 +290,121 @@ class RasterizerEffectsRD { } bokeh; enum SSAOMode { - SSAO_MINIFY_FIRST, - SSAO_MINIFY_MIPMAP, - SSAO_GATHER_LOW, - SSAO_GATHER_MEDIUM, - SSAO_GATHER_HIGH, - SSAO_GATHER_ULTRA, - SSAO_GATHER_LOW_HALF, - SSAO_GATHER_MEDIUM_HALF, - SSAO_GATHER_HIGH_HALF, - SSAO_GATHER_ULTRA_HALF, + SSAO_DOWNSAMPLE, + SSAO_DOWNSAMPLE_HALF_RES, + SSAO_DOWNSAMPLE_MIPMAP, + SSAO_DOWNSAMPLE_MIPMAP_HALF_RES, + SSAO_DOWNSAMPLE_HALF, + SSAO_DOWNSAMPLE_HALF_RES_HALF, + SSAO_GATHER, + SSAO_GATHER_BASE, + SSAO_GATHER_ADAPTIVE, + SSAO_GENERATE_IMPORTANCE_MAP, + SSAO_PROCESS_IMPORTANCE_MAPA, + SSAO_PROCESS_IMPORTANCE_MAPB, SSAO_BLUR_PASS, - SSAO_BLUR_PASS_HALF, - SSAO_BLUR_UPSCALE, + SSAO_BLUR_PASS_SMART, + SSAO_BLUR_PASS_WIDE, + SSAO_INTERLEAVE, + SSAO_INTERLEAVE_SMART, + SSAO_INTERLEAVE_HALF, SSAO_MAX }; - struct SSAOMinifyPushConstant { + struct SSAODownsamplePushConstant { float pixel_size[2]; float z_far; float z_near; - int32_t source_size[2]; uint32_t orthogonal; - uint32_t pad; + float radius_sq; + uint32_t pad[2]; }; struct SSAOGatherPushConstant { int32_t screen_size[2]; - float z_far; - float z_near; + int pass; + int quality; + + float half_screen_pixel_size[2]; + int size_multiplier; + float detail_intensity; + + float NDC_to_view_mul[2]; + float NDC_to_view_add[2]; + + float pad[2]; + float half_screen_pixel_size_x025[2]; - uint32_t orthogonal; - float intensity_div_r6; float radius; - float bias; + float intensity; + float shadow_power; + float shadow_clamp; - float proj_info[4]; - float pixel_size[2]; - float proj_scale; - uint32_t pad; + float fade_out_mul; + float fade_out_add; + float horizon_angle_threshold; + float inv_radius_near_limit; + + bool is_orthogonal; + float neg_inv_radius; + float load_counter_avg_div; + float adaptive_sample_limit; + + int32_t pass_coord_offset[2]; + float pass_uv_offset[2]; + }; + + struct SSAOGatherConstants { + float rotation_matrices[80]; //5 vec4s * 4 + }; + + struct SSAOImportanceMapPushConstant { + float half_screen_pixel_size[2]; + float intensity; + float power; }; struct SSAOBlurPushConstant { float edge_sharpness; - int32_t filter_scale; - float z_far; - float z_near; - uint32_t orthogonal; - uint32_t pad[3]; - int32_t axis[2]; - int32_t screen_size[2]; + float pad; + float half_screen_pixel_size[2]; + }; + + struct SSAOInterleavePushConstant { + float inv_sharpness; + uint32_t size_modifier; + float pixel_size[2]; }; struct SSAO { - SSAOMinifyPushConstant minify_push_constant; - SsaoMinifyShaderRD minify_shader; - RID minify_shader_version; + SSAODownsamplePushConstant downsample_push_constant; + SsaoDownsampleShaderRD downsample_shader; + RID downsample_shader_version; + RID downsample_uniform_set; SSAOGatherPushConstant gather_push_constant; SsaoShaderRD gather_shader; RID gather_shader_version; + RID gather_uniform_set; + RID gather_constants_buffer; + bool gather_initialized = false; + + SSAOImportanceMapPushConstant importance_map_push_constant; + SsaoImportanceMapShaderRD importance_map_shader; + RID importance_map_shader_version; + RID importance_map_load_counter; + RID importance_map_uniform_set; + RID counter_uniform_set; SSAOBlurPushConstant blur_push_constant; SsaoBlurShaderRD blur_shader; RID blur_shader_version; + SSAOInterleavePushConstant interleave_push_constant; + SsaoInterleaveShaderRD interleave_shader; + RID interleave_shader_version; + + RID mirror_sampler; RID pipelines[SSAO_MAX]; } ssao; @@ -424,7 +478,7 @@ class RasterizerEffectsRD { struct SpecularMerge { SpecularMergeShaderRD shader; RID shader_version; - RenderPipelineVertexFormatCacheRD pipelines[SPECULAR_MERGE_MAX]; + PipelineCacheRD pipelines[SPECULAR_MERGE_MAX]; } specular_merge; @@ -596,13 +650,27 @@ class RasterizerEffectsRD { } }; + struct TextureSamplerPair { + RID texture; + RID sampler; + _FORCE_INLINE_ bool operator<(const TextureSamplerPair &p_pair) const { + if (texture == p_pair.texture) { + return sampler < p_pair.sampler; + } else { + return texture < p_pair.texture; + } + } + }; + Map<RID, RID> texture_to_compute_uniform_set_cache; Map<TexturePair, RID> texture_pair_to_compute_uniform_set_cache; Map<TexturePair, RID> image_pair_to_compute_uniform_set_cache; + Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache; RID _get_uniform_set_from_image(RID p_texture); RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); + RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler); RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false); RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2); @@ -654,6 +722,7 @@ public: float saturation = 1.0; bool use_color_correction = false; + bool use_1d_color_correction = false; RID color_correction_texture; bool use_fxaa = false; @@ -661,14 +730,35 @@ public: Vector2i texture_size; }; + struct SSAOSettings { + float radius = 1.0; + float intensity = 2.0; + float power = 1.5; + float detail = 0.5; + float horizon = 0.06; + float sharpness = 0.98; + + RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM; + bool half_size = false; + float adaptive_target = 0.5; + int blur_passes = 2; + float fadeout_from = 50.0; + float fadeout_to = 300.0; + + Size2i full_screen_size = Size2i(); + Size2i half_screen_size = Size2i(); + Size2i quarter_screen_size = Size2i(); + }; + void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings); - void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, RS::EnvironmentSSAOQuality p_quality, RS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness); + void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass); + void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets); void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve); void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size); void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array); - void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position); + void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_fog, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position); void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera); void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection); @@ -681,8 +771,8 @@ public: void sort_buffer(RID p_uniform_set, int p_size); - RasterizerEffectsRD(); - ~RasterizerEffectsRD(); + EffectsRD(); + ~EffectsRD(); }; #endif // !RASTERIZER_EFFECTS_RD_H diff --git a/servers/rendering/rasterizer_rd/light_cluster_builder.cpp b/servers/rendering/renderer_rd/light_cluster_builder.cpp index efb48e6df7..bb807ca4ca 100644 --- a/servers/rendering/rasterizer_rd/light_cluster_builder.cpp +++ b/servers/rendering/renderer_rd/light_cluster_builder.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -190,7 +190,7 @@ void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_ { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - tf.type = RD::TEXTURE_TYPE_3D; + tf.texture_type = RD::TEXTURE_TYPE_3D; tf.width = width; tf.height = height; tf.depth = depth; diff --git a/servers/rendering/rasterizer_rd/light_cluster_builder.h b/servers/rendering/renderer_rd/light_cluster_builder.h index b1da083dad..8f77ece6f5 100644 --- a/servers/rendering/rasterizer_rd/light_cluster_builder.h +++ b/servers/rendering/renderer_rd/light_cluster_builder.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -31,7 +31,7 @@ #ifndef LIGHT_CLUSTER_BUILDER_H #define LIGHT_CLUSTER_BUILDER_H -#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" class LightClusterBuilder { public: diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp index 5cc3da8d4e..b2b919c40e 100644 --- a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* render_pipeline_vertex_format_cache_rd.cpp */ +/* pipeline_cache_rd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "render_pipeline_vertex_format_cache_rd.h" +#include "pipeline_cache_rd.h" #include "core/os/memory.h" -RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe) { +RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe) { RD::PipelineMultisampleState multisample_state_version = multisample_state; multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id); @@ -49,7 +49,7 @@ RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_ve return pipeline; } -void RenderPipelineVertexFormatCacheRD::_clear() { +void PipelineCacheRD::_clear() { if (versions) { for (uint32_t i = 0; i < version_count; i++) { //shader may be gone, so this may not be valid @@ -63,7 +63,7 @@ void RenderPipelineVertexFormatCacheRD::_clear() { } } -void RenderPipelineVertexFormatCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) { +void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) { ERR_FAIL_COND(p_shader.is_null()); _clear(); shader = p_shader; @@ -76,24 +76,24 @@ void RenderPipelineVertexFormatCacheRD::setup(RID p_shader, RD::RenderPrimitive dynamic_state_flags = p_dynamic_state_flags; } -void RenderPipelineVertexFormatCacheRD::update_shader(RID p_shader) { +void PipelineCacheRD::update_shader(RID p_shader) { ERR_FAIL_COND(p_shader.is_null()); _clear(); setup(p_shader, render_primitive, rasterization_state, multisample_state, depth_stencil_state, blend_state, dynamic_state_flags); } -void RenderPipelineVertexFormatCacheRD::clear() { +void PipelineCacheRD::clear() { _clear(); shader = RID(); //clear shader input_mask = 0; } -RenderPipelineVertexFormatCacheRD::RenderPipelineVertexFormatCacheRD() { +PipelineCacheRD::PipelineCacheRD() { version_count = 0; versions = nullptr; input_mask = 0; } -RenderPipelineVertexFormatCacheRD::~RenderPipelineVertexFormatCacheRD() { +PipelineCacheRD::~PipelineCacheRD() { _clear(); } diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h index 6a72dbc77c..b1c8f21ecc 100644 --- a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h +++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* render_pipeline_vertex_format_cache_rd.h */ +/* pipeline_cache_rd.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDER_PIPELINE_CACHE_RD_H -#define RENDER_PIPELINE_CACHE_RD_H +#ifndef PIPELINE_CACHE_RD_H +#define PIPELINE_CACHE_RD_H #include "core/os/spin_lock.h" #include "servers/rendering/rendering_device.h" -class RenderPipelineVertexFormatCacheRD { +class PipelineCacheRD { SpinLock spin_lock; RID shader; @@ -89,8 +89,8 @@ public: return input_mask; } void clear(); - RenderPipelineVertexFormatCacheRD(); - ~RenderPipelineVertexFormatCacheRD(); + PipelineCacheRD(); + ~PipelineCacheRD(); }; #endif // RENDER_PIPELINE_CACHE_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 921a7b966e..792fcb0b59 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_canvas_rd.cpp */ +/* renderer_canvas_render_rd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rasterizer_canvas_rd.h" +#include "renderer_canvas_render_rd.h" #include "core/config/project_settings.h" #include "core/math/geometry_2d.h" #include "core/math/math_funcs.h" -#include "rasterizer_rd.h" +#include "renderer_compositor_rd.h" -void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) { +void RendererCanvasRenderRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) { p_mat4[0] = p_transform.elements[0][0]; p_mat4[1] = p_transform.elements[0][1]; p_mat4[2] = 0; @@ -53,7 +53,7 @@ void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_trans p_mat4[15] = 1; } -void RasterizerCanvasRD::_update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4) { +void RendererCanvasRenderRD::_update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4) { p_mat2x4[0] = p_transform.elements[0][0]; p_mat2x4[1] = p_transform.elements[1][0]; p_mat2x4[2] = 0; @@ -65,7 +65,7 @@ void RasterizerCanvasRD::_update_transform_2d_to_mat2x4(const Transform2D &p_tra p_mat2x4[7] = p_transform.elements[2][1]; } -void RasterizerCanvasRD::_update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3) { +void RendererCanvasRenderRD::_update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3) { p_mat2x3[0] = p_transform.elements[0][0]; p_mat2x3[1] = p_transform.elements[0][1]; p_mat2x3[2] = p_transform.elements[1][0]; @@ -74,7 +74,7 @@ void RasterizerCanvasRD::_update_transform_2d_to_mat2x3(const Transform2D &p_tra p_mat2x3[5] = p_transform.elements[2][1]; } -void RasterizerCanvasRD::_update_transform_to_mat4(const Transform &p_transform, float *p_mat4) { +void RendererCanvasRenderRD::_update_transform_to_mat4(const Transform &p_transform, float *p_mat4) { p_mat4[0] = p_transform.basis.elements[0][0]; p_mat4[1] = p_transform.basis.elements[1][0]; p_mat4[2] = p_transform.basis.elements[2][0]; @@ -93,7 +93,7 @@ void RasterizerCanvasRD::_update_transform_to_mat4(const Transform &p_transform, p_mat4[15] = 1; } -RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights) { +RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights) { // Care must be taken to generate array formats // in ways where they could be reused, so we will // put single-occuring elements first, and repeated @@ -119,9 +119,9 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int Vector<uint8_t> polygon_buffer; polygon_buffer.resize(buffer_size * sizeof(float)); Vector<RD::VertexAttribute> descriptions; - descriptions.resize(4); + descriptions.resize(5); Vector<RID> buffers; - buffers.resize(4); + buffers.resize(5); { const uint8_t *r = polygon_buffer.ptr(); @@ -184,7 +184,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int vd.stride = 0; descriptions.write[1] = vd; - buffers.write[1] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_COLOR); + buffers.write[1] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_COLOR); } //uvs @@ -212,13 +212,13 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int vd.stride = 0; descriptions.write[2] = vd; - buffers.write[2] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_TEX_UV); + buffers.write[2] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_TEX_UV); } //bones if ((uint32_t)p_indices.size() == vertex_count * 4 && (uint32_t)p_weights.size() == vertex_count * 4) { RD::VertexAttribute vd; - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT; vd.offset = base_offset * sizeof(float); vd.location = RS::ARRAY_BONES; vd.stride = stride * sizeof(float); @@ -226,16 +226,42 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int descriptions.write[3] = vd; const int *bone_ptr = p_bones.ptr(); - const float *weight_ptr = p_weights.ptr(); for (uint32_t i = 0; i < vertex_count; i++) { uint16_t *bone16w = (uint16_t *)&uptr[base_offset + i * stride]; - uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride + 2]; bone16w[0] = bone_ptr[i * 4 + 0]; bone16w[1] = bone_ptr[i * 4 + 1]; bone16w[2] = bone_ptr[i * 4 + 2]; bone16w[3] = bone_ptr[i * 4 + 3]; + } + + base_offset += 2; + } else { + RD::VertexAttribute vd; + vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + vd.offset = 0; + vd.location = RS::ARRAY_BONES; + vd.stride = 0; + + descriptions.write[3] = vd; + buffers.write[3] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_BONES); + } + + //weights + if ((uint32_t)p_weights.size() == vertex_count * 4) { + RD::VertexAttribute vd; + vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM; + vd.offset = base_offset * sizeof(float); + vd.location = RS::ARRAY_WEIGHTS; + vd.stride = stride * sizeof(float); + + descriptions.write[4] = vd; + + const float *weight_ptr = p_weights.ptr(); + + for (uint32_t i = 0; i < vertex_count; i++) { + uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride]; weight16w[0] = CLAMP(weight_ptr[i * 4 + 0] * 65535, 0, 65535); weight16w[1] = CLAMP(weight_ptr[i * 4 + 1] * 65535, 0, 65535); @@ -243,16 +269,16 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int weight16w[3] = CLAMP(weight_ptr[i * 4 + 3] * 65535, 0, 65535); } - base_offset += 4; + base_offset += 2; } else { RD::VertexAttribute vd; - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; vd.offset = 0; - vd.location = RS::ARRAY_BONES; + vd.location = RS::ARRAY_WEIGHTS; vd.stride = 0; - descriptions.write[3] = vd; - buffers.write[3] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES); + descriptions.write[4] = vd; + buffers.write[4] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_BONES); } //check that everything is as it should be @@ -293,7 +319,7 @@ RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int return id; } -void RasterizerCanvasRD::free_polygon(PolygonID p_polygon) { +void RendererCanvasRenderRD::free_polygon(PolygonID p_polygon) { PolygonBuffers *pb_ptr = polygon_buffers.polygons.getptr(p_polygon); ERR_FAIL_COND(!pb_ptr); @@ -314,7 +340,7 @@ void RasterizerCanvasRD::free_polygon(PolygonID p_polygon) { //////////////////// -void RasterizerCanvasRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size) { +void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size) { if (p_texture == RID()) { p_texture = default_canvas_texture; } @@ -364,7 +390,7 @@ void RasterizerCanvasRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_ r_last_texture = p_texture; } -void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) { +void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) { //create an empty push constant RS::CanvasItemTextureFilter current_filter = default_filter; @@ -575,10 +601,10 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ push_constant.flags |= FLAGS_NINEPACH_DRAW_CENTER; } - push_constant.ninepatch_margins[0] = np->margin[MARGIN_LEFT]; - push_constant.ninepatch_margins[1] = np->margin[MARGIN_TOP]; - push_constant.ninepatch_margins[2] = np->margin[MARGIN_RIGHT]; - push_constant.ninepatch_margins[3] = np->margin[MARGIN_BOTTOM]; + push_constant.ninepatch_margins[0] = np->margin[SIDE_LEFT]; + push_constant.ninepatch_margins[1] = np->margin[SIDE_TOP]; + push_constant.ninepatch_margins[2] = np->margin[SIDE_RIGHT]; + push_constant.ninepatch_margins[3] = np->margin[SIDE_BOTTOM]; RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); @@ -848,7 +874,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white - RenderingServerRaster::redraw_request(); + RenderingServerDefault::redraw_request(); storage->particles_request_process(particles_cmd->particles); //enable instancing @@ -990,13 +1016,13 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } } -RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_backbuffer) { +RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, bool p_backbuffer) { //re create canvas state Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 1; u.ids.push_back(state.canvas_state_buffer); uniforms.push_back(u); @@ -1004,7 +1030,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 2; u.ids.push_back(state.lights_uniform_buffer); uniforms.push_back(u); @@ -1012,7 +1038,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 3; u.ids.push_back(storage->decal_atlas_get_texture()); uniforms.push_back(u); @@ -1020,7 +1046,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 4; u.ids.push_back(state.shadow_texture); uniforms.push_back(u); @@ -1028,7 +1054,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 5; u.ids.push_back(state.shadow_sampler); uniforms.push_back(u); @@ -1036,7 +1062,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 6; RID screen; if (p_backbuffer) { @@ -1044,7 +1070,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ } else { screen = storage->render_target_get_rd_backbuffer(p_to_render_target); if (screen.is_null()) { //unallocated backbuffer - screen = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + screen = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); } } u.ids.push_back(screen); @@ -1053,7 +1079,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 7; RID sdf = storage->render_target_get_sdf_texture(p_to_render_target); u.ids.push_back(sdf); @@ -1063,7 +1089,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { //needs samplers for the material (uses custom textures) create them RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 8; u.ids.resize(12); RID *ids_ptr = u.ids.ptrw(); @@ -1084,7 +1110,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 9; u.ids.push_back(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); @@ -1100,7 +1126,7 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_ return uniform_set; } -void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) { +void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) { Item *current_clip = nullptr; Transform2D canvas_transform_inverse = p_canvas_transform_inverse; @@ -1167,7 +1193,7 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, if (material != prev_material) { MaterialData *material_data = nullptr; if (material.is_valid()) { - material_data = (MaterialData *)storage->material_get_data(material, RasterizerStorageRD::SHADER_TYPE_2D); + material_data = (MaterialData *)storage->material_get_data(material, RendererStorageRD::SHADER_TYPE_2D); } if (material_data) { @@ -1192,7 +1218,7 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, RD::get_singleton()->draw_list_end(); } -void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) { +void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) { r_sdf_used = false; int item_count = 0; @@ -1423,7 +1449,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite } if (ci->material.is_valid()) { - MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); + MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RendererStorageRD::SHADER_TYPE_2D); if (md && md->shader_data->valid) { if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) { if (!material_screen_texture_found) { @@ -1435,12 +1461,12 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite if (md->shader_data->uses_sdf) { r_sdf_used = true; } - if (md->last_frame != RasterizerRD::singleton->get_frame_number()) { - md->last_frame = RasterizerRD::singleton->get_frame_number(); + if (md->last_frame != RendererCompositorRD::singleton->get_frame_number()) { + md->last_frame = RendererCompositorRD::singleton->get_frame_number(); if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) { // uniform set may be gone because a dependency was erased. In this case, it will happen // if a texture is deleted, so just re-create it. - storage->material_force_update_textures(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); + storage->material_force_update_textures(ci->material, RendererStorageRD::SHADER_TYPE_2D); } } } @@ -1501,12 +1527,12 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite } } -RID RasterizerCanvasRD::light_create() { +RID RendererCanvasRenderRD::light_create() { CanvasLight canvas_light; return canvas_light_owner.make_rid(canvas_light); } -void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) { +void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); ERR_FAIL_COND(!cl); if (cl->texture == p_texture) { @@ -1522,14 +1548,14 @@ void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) { } } -void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable) { +void RendererCanvasRenderRD::light_set_use_shadow(RID p_rid, bool p_enable) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); ERR_FAIL_COND(!cl); cl->shadow.enabled = p_enable; } -void RasterizerCanvasRD::_update_shadow_atlas() { +void RendererCanvasRenderRD::_update_shadow_atlas() { if (state.shadow_fb == RID()) { //ah, we lack the shadow texture.. RD::get_singleton()->free(state.shadow_texture); //erase placeholder @@ -1538,7 +1564,7 @@ void RasterizerCanvasRD::_update_shadow_atlas() { { //texture RD::TextureFormat tf; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.width = state.shadow_texture_size; tf.height = state.max_lights_per_render * 2; tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; @@ -1549,7 +1575,7 @@ void RasterizerCanvasRD::_update_shadow_atlas() { } { RD::TextureFormat tf; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.width = state.shadow_texture_size; tf.height = state.max_lights_per_render * 2; tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; @@ -1562,7 +1588,7 @@ void RasterizerCanvasRD::_update_shadow_atlas() { state.shadow_fb = RD::get_singleton()->framebuffer_create(fb_textures); } } -void RasterizerCanvasRD::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { +void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); ERR_FAIL_COND(!cl->shadow.enabled); @@ -1640,7 +1666,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, int p_shadow_index, cons } } -void RasterizerCanvasRD::light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) { +void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); ERR_FAIL_COND(!cl->shadow.enabled); @@ -1663,7 +1689,7 @@ void RasterizerCanvasRD::light_update_directional_shadow(RID p_rid, int p_shadow to_light_xform[2] = from_pos; to_light_xform[1] = light_dir; - to_light_xform[0] = -light_dir.tangent(); + to_light_xform[0] = -light_dir.orthogonal(); to_light_xform.invert(); @@ -1720,7 +1746,7 @@ void RasterizerCanvasRD::light_update_directional_shadow(RID p_rid, int p_shadow cl->shadow.directional_xform = to_shadow * to_light_xform; } -void RasterizerCanvasRD::render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) { +void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) { RID fb = storage->render_target_get_sdf_framebuffer(p_render_target); Rect2i rect = storage->render_target_get_sdf_rect(p_render_target); @@ -1782,7 +1808,7 @@ void RasterizerCanvasRD::render_sdf(RID p_render_target, LightOccluderInstance * storage->render_target_sdf_process(p_render_target); //done rendering, process it } -RID RasterizerCanvasRD::occluder_polygon_create() { +RID RendererCanvasRenderRD::occluder_polygon_create() { OccluderPolygon occluder; occluder.line_point_count = 0; occluder.sdf_point_count = 0; @@ -1791,27 +1817,30 @@ RID RasterizerCanvasRD::occluder_polygon_create() { return occluder_polygon_owner.make_rid(occluder); } -void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) { +void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Vector<Vector2> &p_points, bool p_closed) { OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); ERR_FAIL_COND(!oc); Vector<Vector2> lines; - int lc = p_points.size() * 2; - lines.resize(lc - (p_closed ? 0 : 2)); - { - Vector2 *w = lines.ptrw(); - const Vector2 *r = p_points.ptr(); + if (p_points.size()) { + int lc = p_points.size() * 2; - int max = lc / 2; - if (!p_closed) { - max--; - } - for (int i = 0; i < max; i++) { - Vector2 a = r[i]; - Vector2 b = r[(i + 1) % (lc / 2)]; - w[i * 2 + 0] = a; - w[i * 2 + 1] = b; + lines.resize(lc - (p_closed ? 0 : 2)); + { + Vector2 *w = lines.ptrw(); + const Vector2 *r = p_points.ptr(); + + int max = lc / 2; + if (!p_closed) { + max--; + } + for (int i = 0; i < max; i++) { + Vector2 a = r[i]; + Vector2 b = r[(i + 1) % (lc / 2)]; + w[i * 2 + 0] = a; + w[i * 2 + 1] = b; + } } } @@ -1832,7 +1861,7 @@ void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector if (lines.size()) { Vector<uint8_t> geometry; Vector<uint8_t> indices; - lc = lines.size(); + int lc = lines.size(); geometry.resize(lc * 6 * sizeof(float)); indices.resize(lc * 3 * sizeof(uint16_t)); @@ -1902,19 +1931,21 @@ void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector Vector<int> sdf_indices; - if (p_closed) { - sdf_indices = Geometry2D::triangulate_polygon(p_points); - oc->sdf_is_lines = false; - } else { - int max = p_points.size(); - sdf_indices.resize(max * 2); + if (p_points.size()) { + if (p_closed) { + sdf_indices = Geometry2D::triangulate_polygon(p_points); + oc->sdf_is_lines = false; + } else { + int max = p_points.size(); + sdf_indices.resize(max * 2); - int *iw = sdf_indices.ptrw(); - for (int i = 0; i < max; i++) { - iw[i * 2 + 0] = i; - iw[i * 2 + 1] = (i + 1) % max; + int *iw = sdf_indices.ptrw(); + for (int i = 0; i < max; i++) { + iw[i * 2 + 0] = i; + iw[i * 2 + 1] = (i + 1) % max; + } + oc->sdf_is_lines = true; } - oc->sdf_is_lines = true; } if (oc->sdf_index_count != sdf_indices.size() && oc->sdf_point_count != p_points.size() && oc->sdf_vertex_array.is_valid()) { @@ -1955,13 +1986,13 @@ void RasterizerCanvasRD::occluder_polygon_set_shape(RID p_occluder, const Vector } } -void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) { +void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) { OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); ERR_FAIL_COND(!oc); oc->cull_mode = p_mode; } -void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { +void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -1994,7 +2025,7 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; - RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; + RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code); @@ -2139,7 +2170,7 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { valid = true; } -void RasterizerCanvasRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererCanvasRenderRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { if (!p_texture.is_valid()) { default_texture_params.erase(p_name); } else { @@ -2147,7 +2178,7 @@ void RasterizerCanvasRD::ShaderData::set_default_texture_param(const StringName } } -void RasterizerCanvasRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void RendererCanvasRenderRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { Map<int, StringName> order; for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { @@ -2168,13 +2199,13 @@ void RasterizerCanvasRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_ } } -void RasterizerCanvasRD::ShaderData::get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const { +void RendererCanvasRenderRD::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RasterizerStorage::InstanceShaderParam p; + RendererStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E->get()); p.info.name = E->key(); //supply name p.index = E->get().instance_index; @@ -2183,7 +2214,7 @@ void RasterizerCanvasRD::ShaderData::get_instance_param_list(List<RasterizerStor } } -bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param) const { +bool RendererCanvasRenderRD::ShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -2191,15 +2222,15 @@ bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param) return uniforms[p_param].texture_order >= 0; } -bool RasterizerCanvasRD::ShaderData::is_animated() const { +bool RendererCanvasRenderRD::ShaderData::is_animated() const { return false; } -bool RasterizerCanvasRD::ShaderData::casts_shadows() const { +bool RendererCanvasRenderRD::ShaderData::casts_shadows() const { return false; } -Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -2208,14 +2239,19 @@ Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName & return Variant(); } -RasterizerCanvasRD::ShaderData::ShaderData() { +RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const { + RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; + return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version); +} + +RendererCanvasRenderRD::ShaderData::ShaderData() { valid = false; uses_screen_texture = false; uses_sdf = false; } -RasterizerCanvasRD::ShaderData::~ShaderData() { - RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; +RendererCanvasRenderRD::ShaderData::~ShaderData() { + RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; ERR_FAIL_COND(!canvas_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -2223,13 +2259,13 @@ RasterizerCanvasRD::ShaderData::~ShaderData() { } } -RasterizerStorageRD::ShaderData *RasterizerCanvasRD::_create_shader_func() { +RendererStorageRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); return shader_data; } -void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; +void RendererCanvasRenderRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { p_uniform_dirty = true; @@ -2289,7 +2325,7 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V { if (shader_data->ubo_size) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 0; u.ids.push_back(uniform_buffer); uniforms.push_back(u); @@ -2298,7 +2334,7 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V const RID *textures = texture_cache.ptrw(); for (uint32_t i = 0; i < tex_uniform_count; i++) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1 + i; u.ids.push_back(textures[i]); uniforms.push_back(u); @@ -2308,7 +2344,7 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } -RasterizerCanvasRD::MaterialData::~MaterialData() { +RendererCanvasRenderRD::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } @@ -2318,7 +2354,7 @@ RasterizerCanvasRD::MaterialData::~MaterialData() { } } -RasterizerStorageRD::MaterialData *RasterizerCanvasRD::_create_material_func(ShaderData *p_shader) { +RendererStorageRD::MaterialData *RendererCanvasRenderRD::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; material_data->last_frame = false; @@ -2326,14 +2362,14 @@ RasterizerStorageRD::MaterialData *RasterizerCanvasRD::_create_material_func(Sha return material_data; } -void RasterizerCanvasRD::set_time(double p_time) { +void RendererCanvasRenderRD::set_time(double p_time) { state.time = p_time; } -void RasterizerCanvasRD::update() { +void RendererCanvasRenderRD::update() { } -RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { +RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { storage = p_storage; { //create default samplers @@ -2457,8 +2493,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { actions.renames["COLOR"] = "color"; actions.renames["NORMAL"] = "normal"; - actions.renames["NORMALMAP"] = "normal_map"; - actions.renames["NORMALMAP_DEPTH"] = "normal_depth"; + actions.renames["NORMAL_MAP"] = "normal_map"; + actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; actions.renames["TEXTURE"] = "color_texture"; actions.renames["TEXTURE_PIXEL_SIZE"] = "draw_data.color_texture_pixel_size"; actions.renames["NORMAL_TEXTURE"] = "normal_texture"; @@ -2470,7 +2506,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { actions.renames["FRAGCOORD"] = "gl_FragCoord"; actions.renames["POINT_COORD"] = "gl_PointCoord"; - actions.renames["LIGHT_POSITION"] = "light_pos"; + actions.renames["LIGHT_POSITION"] = "light_position"; actions.renames["LIGHT_COLOR"] = "light_color"; actions.renames["LIGHT_ENERGY"] = "light_energy"; actions.renames["LIGHT"] = "light"; @@ -2486,7 +2522,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; - actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; + actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; @@ -2636,7 +2672,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { //default shadow texture to keep uniform set happy RD::TextureFormat tf; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.width = 4; tf.height = 4; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; @@ -2650,7 +2686,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; u.ids.push_back(storage->get_default_rd_storage_buffer()); uniforms.push_back(u); @@ -2664,8 +2700,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { state.shadow_texture_size = GLOBAL_GET("rendering/quality/2d_shadow_atlas/size"); //create functions for shader and material - storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_shader_funcs); - storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_material_funcs); + storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_shader_funcs); + storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_2D, _create_material_funcs); state.time = 0; @@ -2679,7 +2715,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { static_assert(sizeof(PushConstant) == 128); } -bool RasterizerCanvasRD::free(RID p_rid) { +bool RendererCanvasRenderRD::free(RID p_rid) { if (canvas_light_owner.owns(p_rid)) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); ERR_FAIL_COND_V(!cl, false); @@ -2695,7 +2731,7 @@ bool RasterizerCanvasRD::free(RID p_rid) { return true; } -void RasterizerCanvasRD::set_shadow_texture_size(int p_size) { +void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) { p_size = nearest_power_of_2_templated(p_size); if (p_size == state.shadow_texture_size) { return; @@ -2709,7 +2745,7 @@ void RasterizerCanvasRD::set_shadow_texture_size(int p_size) { { //create a default shadow texture to keep uniform set happy (and that it gets erased when a new one is created) RD::TextureFormat tf; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.width = 4; tf.height = 4; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; @@ -2720,7 +2756,7 @@ void RasterizerCanvasRD::set_shadow_texture_size(int p_size) { } } -RasterizerCanvasRD::~RasterizerCanvasRD() { +RendererCanvasRenderRD::~RendererCanvasRenderRD() { //canvas state storage->free(default_canvas_group_material); diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index b09d6578f3..cb947d7180 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_canvas_rd.h */ +/* renderer_canvas_render_rd.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,19 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_CANVAS_RD_H -#define RASTERIZER_CANVAS_RD_H +#ifndef RENDERING_SERVER_CANVAS_RENDER_RD_H +#define RENDERING_SERVER_CANVAS_RENDER_RD_H -#include "servers/rendering/rasterizer.h" -#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" -#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" -#include "servers/rendering/rasterizer_rd/shader_compiler_rd.h" -#include "servers/rendering/rasterizer_rd/shaders/canvas.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl.gen.h" +#include "servers/rendering/renderer_canvas_render.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" +#include "servers/rendering/renderer_rd/shader_compiler_rd.h" +#include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h" #include "servers/rendering/rendering_device.h" -class RasterizerCanvasRD : public RasterizerCanvas { - RasterizerStorageRD *storage; +class RendererCanvasRenderRD : public RendererCanvasRender { + RendererStorageRD *storage; enum { BASE_UNIFORM_SET = 0, @@ -133,7 +134,7 @@ class RasterizerCanvasRD : public RasterizerCanvas { }; struct PipelineVariants { - RenderPipelineVertexFormatCacheRD variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX]; + PipelineCacheRD variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX]; }; struct { @@ -151,7 +152,7 @@ class RasterizerCanvasRD : public RasterizerCanvas { ShaderCompilerRD compiler; } shader; - struct ShaderData : public RasterizerStorageRD::ShaderData { + struct ShaderData : public RendererStorageRD::ShaderData { enum BlendMode { //used internally BLEND_MODE_MIX, BLEND_MODE_ADD, @@ -181,22 +182,24 @@ class RasterizerCanvasRD : public RasterizerCanvas { virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererStorage::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; + ShaderData(); virtual ~ShaderData(); }; - RasterizerStorageRD::ShaderData *_create_shader_func(); - static RasterizerStorageRD::ShaderData *_create_shader_funcs() { - return static_cast<RasterizerCanvasRD *>(singleton)->_create_shader_func(); + RendererStorageRD::ShaderData *_create_shader_func(); + static RendererStorageRD::ShaderData *_create_shader_funcs() { + return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func(); } - struct MaterialData : public RasterizerStorageRD::MaterialData { + struct MaterialData : public RendererStorageRD::MaterialData { uint64_t last_frame; ShaderData *shader_data; RID uniform_buffer; @@ -210,9 +213,9 @@ class RasterizerCanvasRD : public RasterizerCanvas { virtual ~MaterialData(); }; - RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { - return static_cast<RasterizerCanvasRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); + RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { + return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); } /**************************/ @@ -462,8 +465,8 @@ public: void set_time(double p_time); void update(); bool free(RID p_rid); - RasterizerCanvasRD(RasterizerStorageRD *p_storage); - ~RasterizerCanvasRD(); + RendererCanvasRenderRD(RendererStorageRD *p_storage); + ~RendererCanvasRenderRD(); }; #endif // RASTERIZER_CANVAS_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 5f8cf0ee8c..be2552bd32 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_rd.cpp */ +/* renderer_compositor_rd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rasterizer_rd.h" +#include "renderer_compositor_rd.h" #include "core/config/project_settings.h" -void RasterizerRD::prepare_for_blitting_render_targets() { +void RendererCompositorRD::prepare_for_blitting_render_targets() { RD::get_singleton()->prepare_screen_for_drawing(); } -void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { +void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen); for (int i = 0; i < p_amount; i++) { @@ -47,7 +47,7 @@ void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_scree if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) { Vector<RD::Uniform> uniforms; RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; u.ids.push_back(copy_viewports_sampler); u.ids.push_back(rd_texture); @@ -76,7 +76,7 @@ void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_scree RD::get_singleton()->draw_list_end(); } -void RasterizerRD::begin_frame(double frame_step) { +void RendererCompositorRD::begin_frame(double frame_step) { frame++; delta = frame_step; time += frame_step; @@ -88,14 +88,14 @@ void RasterizerRD::begin_frame(double frame_step) { scene->set_time(time, frame_step); } -void RasterizerRD::end_frame(bool p_swap_buffers) { +void RendererCompositorRD::end_frame(bool p_swap_buffers) { #ifndef _MSC_VER #warning TODO: likely pass a bool to swap buffers to avoid display? #endif RD::get_singleton()->swap_buffers(); //probably should pass some bool to avoid display? } -void RasterizerRD::initialize() { +void RendererCompositorRD::initialize() { { //create framebuffer copy shader RenderingDevice::ShaderStageData vert; vert.shader_stage = RenderingDevice::SHADER_STAGE_VERTEX; @@ -154,12 +154,9 @@ void RasterizerRD::initialize() { } } -ThreadWorkPool RasterizerRD::thread_work_pool; -uint64_t RasterizerRD::frame = 1; - -void RasterizerRD::finalize() { - thread_work_pool.finish(); +uint64_t RendererCompositorRD::frame = 1; +void RendererCompositorRD::finalize() { memdelete(scene); memdelete(canvas); memdelete(storage); @@ -170,14 +167,13 @@ void RasterizerRD::finalize() { RD::get_singleton()->free(copy_viewports_sampler); } -RasterizerRD *RasterizerRD::singleton = nullptr; +RendererCompositorRD *RendererCompositorRD::singleton = nullptr; -RasterizerRD::RasterizerRD() { +RendererCompositorRD::RendererCompositorRD() { singleton = this; - thread_work_pool.init(); time = 0; - storage = memnew(RasterizerStorageRD); - canvas = memnew(RasterizerCanvasRD(storage)); - scene = memnew(RasterizerSceneHighEndRD(storage)); + storage = memnew(RendererStorageRD); + canvas = memnew(RendererCanvasRenderRD(storage)); + scene = memnew(RendererSceneRenderForward(storage)); } diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 59fb8d2049..cb85fc79e0 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_rd.h */ +/* renderer_compositor_rd.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,21 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_RD_H -#define RASTERIZER_RD_H +#ifndef RENDERING_SERVER_COMPOSITOR_RD_H +#define RENDERING_SERVER_COMPOSITOR_RD_H #include "core/os/os.h" #include "core/templates/thread_work_pool.h" -#include "servers/rendering/rasterizer.h" -#include "servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h" -#include "servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h" -#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_forward.h" +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" -class RasterizerRD : public Rasterizer { +class RendererCompositorRD : public RendererCompositor { protected: - RasterizerCanvasRD *canvas; - RasterizerStorageRD *storage; - RasterizerSceneHighEndRD *scene; + RendererCanvasRenderRD *canvas; + RendererStorageRD *storage; + RendererSceneRenderForward *scene; RID copy_viewports_rd_shader; RID copy_viewports_rd_pipeline; @@ -58,9 +58,9 @@ protected: static uint64_t frame; public: - RasterizerStorage *get_storage() { return storage; } - RasterizerCanvas *get_canvas() { return canvas; } - RasterizerScene *get_scene() { return scene; } + RendererStorage *get_storage() { return storage; } + RendererCanvasRender *get_canvas() { return canvas; } + RendererSceneRender *get_scene() { return scene; } void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {} @@ -80,8 +80,8 @@ public: return OK; } - static Rasterizer *_create_current() { - return memnew(RasterizerRD); + static RendererCompositor *_create_current() { + return memnew(RendererCompositorRD); } static void make_current() { @@ -90,10 +90,8 @@ public: virtual bool is_low_end() const { return false; } - static ThreadWorkPool thread_work_pool; - - static RasterizerRD *singleton; - RasterizerRD(); - ~RasterizerRD() {} + static RendererCompositorRD *singleton; + RendererCompositorRD(); + ~RendererCompositorRD() {} }; #endif // RASTERIZER_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp index 313188ba87..74556f8105 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_scene_high_end_rd.cpp */ +/* renderer_scene_render_forward.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rasterizer_scene_high_end_rd.h" +#include "renderer_scene_render_forward.h" #include "core/config/project_settings.h" #include "servers/rendering/rendering_device.h" -#include "servers/rendering/rendering_server_raster.h" +#include "servers/rendering/rendering_server_default.h" /* SCENE SHADER */ -void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { +void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -112,7 +112,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["TIME"] = &uses_time; actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; actions.usage_flag_pointers["NORMAL"] = &uses_normal; - actions.usage_flag_pointers["NORMALMAP"] = &uses_normal; + actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal; actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size; actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size; @@ -123,7 +123,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; + RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; Error err = scene_singleton->shader.compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code); @@ -257,6 +257,9 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j]; for (int k = 0; k < SHADER_VERSION_MAX; k++) { + if (!static_cast<RendererSceneRenderForward *>(singleton)->shader.scene_shader.is_variant_enabled(k)) { + continue; + } RD::PipelineRasterizationState raster_state; raster_state.cull_mode = cull_mode_rd; raster_state.wireframe = wireframe; @@ -321,7 +324,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { valid = true; } -void RasterizerSceneHighEndRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererSceneRenderForward::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { if (!p_texture.is_valid()) { default_texture_params.erase(p_name); } else { @@ -329,7 +332,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_default_texture_param(const Strin } } -void RasterizerSceneHighEndRD::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void RendererSceneRenderForward::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { Map<int, StringName> order; for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { @@ -351,13 +354,13 @@ void RasterizerSceneHighEndRD::ShaderData::get_param_list(List<PropertyInfo> *p_ } } -void RasterizerSceneHighEndRD::ShaderData::get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const { +void RendererSceneRenderForward::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RasterizerStorage::InstanceShaderParam p; + RendererStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E->get()); p.info.name = E->key(); //supply name p.index = E->get().instance_index; @@ -366,7 +369,7 @@ void RasterizerSceneHighEndRD::ShaderData::get_instance_param_list(List<Rasteriz } } -bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_param) const { +bool RendererSceneRenderForward::ShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -374,15 +377,15 @@ bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_ return uniforms[p_param].texture_order >= 0; } -bool RasterizerSceneHighEndRD::ShaderData::is_animated() const { +bool RendererSceneRenderForward::ShaderData::is_animated() const { return false; } -bool RasterizerSceneHighEndRD::ShaderData::casts_shadows() const { +bool RendererSceneRenderForward::ShaderData::casts_shadows() const { return false; } -Variant RasterizerSceneHighEndRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -391,13 +394,19 @@ Variant RasterizerSceneHighEndRD::ShaderData::get_default_parameter(const String return Variant(); } -RasterizerSceneHighEndRD::ShaderData::ShaderData() { +RS::ShaderNativeSourceCode RendererSceneRenderForward::ShaderData::get_native_source_code() const { + RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; + + return scene_singleton->shader.scene_shader.version_get_native_source_code(version); +} + +RendererSceneRenderForward::ShaderData::ShaderData() { valid = false; uses_screen_texture = false; } -RasterizerSceneHighEndRD::ShaderData::~ShaderData() { - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; +RendererSceneRenderForward::ShaderData::~ShaderData() { + RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -405,21 +414,21 @@ RasterizerSceneHighEndRD::ShaderData::~ShaderData() { } } -RasterizerStorageRD::ShaderData *RasterizerSceneHighEndRD::_create_shader_func() { +RendererStorageRD::ShaderData *RendererSceneRenderForward::_create_shader_func() { ShaderData *shader_data = memnew(ShaderData); return shader_data; } -void RasterizerSceneHighEndRD::MaterialData::set_render_priority(int p_priority) { +void RendererSceneRenderForward::MaterialData::set_render_priority(int p_priority) { priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits } -void RasterizerSceneHighEndRD::MaterialData::set_next_pass(RID p_pass) { +void RendererSceneRenderForward::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; +void RendererSceneRenderForward::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { p_uniform_dirty = true; @@ -479,7 +488,7 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringN { if (shader_data->ubo_size) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 0; u.ids.push_back(uniform_buffer); uniforms.push_back(u); @@ -488,7 +497,7 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringN const RID *textures = texture_cache.ptrw(); for (uint32_t i = 0; i < tex_uniform_count; i++) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1 + i; u.ids.push_back(textures[i]); uniforms.push_back(u); @@ -498,7 +507,7 @@ void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map<StringN uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } -RasterizerSceneHighEndRD::MaterialData::~MaterialData() { +RendererSceneRenderForward::MaterialData::~MaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } @@ -508,7 +517,7 @@ RasterizerSceneHighEndRD::MaterialData::~MaterialData() { } } -RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_material_func(ShaderData *p_shader) { +RendererStorageRD::MaterialData *RendererSceneRenderForward::_create_material_func(ShaderData *p_shader) { MaterialData *material_data = memnew(MaterialData); material_data->shader_data = p_shader; material_data->last_frame = false; @@ -516,11 +525,11 @@ RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_material_fu return material_data; } -RasterizerSceneHighEndRD::RenderBufferDataHighEnd::~RenderBufferDataHighEnd() { +RendererSceneRenderForward::RenderBufferDataForward::~RenderBufferDataForward() { clear(); } -void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() { +void RendererSceneRenderForward::RenderBufferDataForward::ensure_specular() { if (!specular.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; @@ -574,7 +583,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() { } } -void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_gi() { +void RendererSceneRenderForward::RenderBufferDataForward::ensure_gi() { if (!reflection_buffer.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; @@ -587,7 +596,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_gi() { } } -void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_giprobe() { +void RendererSceneRenderForward::RenderBufferDataForward::ensure_giprobe() { if (!giprobe_buffer.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8_UINT; @@ -623,7 +632,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_giprobe() { } } -void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { +void RendererSceneRenderForward::RenderBufferDataForward::clear() { if (ambient_buffer != RID() && ambient_buffer != color) { RD::get_singleton()->free(ambient_buffer); ambient_buffer = RID(); @@ -687,7 +696,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { } } -void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { +void RendererSceneRenderForward::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { clear(); msaa = p_msaa; @@ -717,7 +726,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_bu tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = p_width; tf.height = p_height; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { @@ -754,7 +763,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_bu } } -void RasterizerSceneHighEndRD::_allocate_normal_roughness_texture(RenderBufferDataHighEnd *rb) { +void RendererSceneRenderForward::_allocate_normal_roughness_texture(RenderBufferDataForward *rb) { if (rb->normal_roughness_buffer.is_valid()) { return; } @@ -763,7 +772,7 @@ void RasterizerSceneHighEndRD::_allocate_normal_roughness_texture(RenderBufferDa tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; tf.width = rb->width; tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; @@ -779,7 +788,7 @@ void RasterizerSceneHighEndRD::_allocate_normal_roughness_texture(RenderBufferDa fb.push_back(rb->normal_roughness_buffer); rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); } else { - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; tf.samples = rb->texture_samples; rb->normal_roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -792,264 +801,100 @@ void RasterizerSceneHighEndRD::_allocate_normal_roughness_texture(RenderBufferDa _render_buffers_clear_uniform_set(rb); } -RasterizerSceneRD::RenderBufferData *RasterizerSceneHighEndRD::_create_render_buffer_data() { - return memnew(RenderBufferDataHighEnd); +RendererSceneRenderRD::RenderBufferData *RendererSceneRenderForward::_create_render_buffer_data() { + return memnew(RenderBufferDataForward); } -bool RasterizerSceneHighEndRD::free(RID p_rid) { - if (RasterizerSceneRD::free(p_rid)) { +bool RendererSceneRenderForward::free(RID p_rid) { + if (RendererSceneRenderRD::free(p_rid)) { return true; } return false; } -void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi, bool p_has_opaque_gi) { - uint32_t lightmap_captures_used = 0; - - for (int i = 0; i < p_element_count; i++) { - const RenderList::Element *e = p_elements[i]; - InstanceData &id = scene_state.instances[i]; - bool store_transform = true; - id.flags = 0; - id.mask = e->instance->layer_mask; - id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0; - - if (e->instance->base_type == RS::INSTANCE_MULTIMESH) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH; - uint32_t stride; - if (storage->multimesh_get_transform_format(e->instance->base) == RS::MULTIMESH_TRANSFORM_2D) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; - stride = 2; - } else { - stride = 3; - } - if (storage->multimesh_uses_colors(e->instance->base)) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; - stride += 1; - } - if (storage->multimesh_uses_custom_data(e->instance->base)) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; - stride += 1; - } - - id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); - } else if (e->instance->base_type == RS::INSTANCE_PARTICLES) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH; - uint32_t stride; - if (false) { // 2D particles - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; - stride = 2; - } else { - stride = 3; - } - - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; - stride += 1; - - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; - stride += 1; - - id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); - - if (!storage->particles_is_using_local_coords(e->instance->base)) { - store_transform = false; - } - - } else if (e->instance->base_type == RS::INSTANCE_MESH) { - if (e->instance->skeleton.is_valid()) { - id.flags |= INSTANCE_DATA_FLAG_SKELETON; - } - } - - if (store_transform) { - RasterizerStorageRD::store_transform(e->instance->transform, id.transform); - RasterizerStorageRD::store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform); - } else { - RasterizerStorageRD::store_transform(Transform(), id.transform); - RasterizerStorageRD::store_transform(Transform(), id.normal_transform); - } - - if (p_for_depth) { - id.gi_offset = 0xFFFFFFFF; - continue; - } - - if (e->instance->lightmap) { - int32_t lightmap_index = storage->lightmap_get_array_index(e->instance->lightmap->base); - if (lightmap_index >= 0) { - id.gi_offset = lightmap_index; - id.gi_offset |= e->instance->lightmap_slice_index << 12; - id.gi_offset |= e->instance->lightmap_cull_index << 20; - id.lightmap_uv_scale[0] = e->instance->lightmap_uv_scale.position.x; - id.lightmap_uv_scale[1] = e->instance->lightmap_uv_scale.position.y; - id.lightmap_uv_scale[2] = e->instance->lightmap_uv_scale.size.width; - id.lightmap_uv_scale[3] = e->instance->lightmap_uv_scale.size.height; - id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP; - if (storage->lightmap_uses_spherical_harmonics(e->instance->lightmap->base)) { - id.flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP; - } - } else { - id.gi_offset = 0xFFFFFFFF; - } - } else if (!e->instance->lightmap_sh.empty()) { - if (lightmap_captures_used < scene_state.max_lightmap_captures) { - const Color *src_capture = e->instance->lightmap_sh.ptr(); - LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used]; - for (int j = 0; j < 9; j++) { - lcd.sh[j * 4 + 0] = src_capture[j].r; - lcd.sh[j * 4 + 1] = src_capture[j].g; - lcd.sh[j * 4 + 2] = src_capture[j].b; - lcd.sh[j * 4 + 3] = src_capture[j].a; - } - id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE; - id.gi_offset = lightmap_captures_used; - lightmap_captures_used++; - } - - } else { - if (p_has_opaque_gi) { - id.flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS; - } - - if (!e->instance->gi_probe_instances.empty()) { - uint32_t written = 0; - for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) { - RID probe = e->instance->gi_probe_instances[j]; - - uint32_t index = gi_probe_instance_get_render_index(probe); - - if (written == 0) { - id.gi_offset = index; - id.flags |= INSTANCE_DATA_FLAG_USE_GIPROBE; - written = 1; - } else { - id.gi_offset = index << 16; - written = 2; - break; - } - } - if (written == 0) { - id.gi_offset = 0xFFFFFFFF; - } else if (written == 1) { - id.gi_offset |= 0xFFFF0000; - } - } else { - if (p_has_sdfgi && (e->instance->baked_light || e->instance->dynamic_gi)) { - id.flags |= INSTANCE_DATA_FLAG_USE_SDFGI; - } - id.gi_offset = 0xFFFFFFFF; - } - } - } - - RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true); - if (lightmap_captures_used) { - RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true); - } -} - /// RENDERING /// -void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset) { +template <RendererSceneRenderForward::PassMode p_pass_mode> +void RendererSceneRenderForward::_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) { RD::DrawListID draw_list = p_draw_list; RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; //global scope bindings RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, SCENE_UNIFORM_SET); - if (p_radiance_uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_radiance_uniform_set, RADIANCE_UNIFORM_SET); - } else { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_radiance_uniform_set, RADIANCE_UNIFORM_SET); - } - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, view_dependant_uniform_set, VIEW_DEPENDANT_UNIFORM_SET); - if (p_render_buffers_uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); - } else { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); - } + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_params->render_pass_uniform_set, RENDER_PASS_UNIFORM_SET); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET); - MaterialData *prev_material = nullptr; + RID prev_material_uniform_set; RID prev_vertex_array_rd; RID prev_index_array_rd; RID prev_pipeline_rd; RID prev_xforms_uniform_set; - PushConstant push_constant; - zeromem(&push_constant, sizeof(PushConstant)); - push_constant.bake_uv2_offset[0] = p_uv_offset.x; - push_constant.bake_uv2_offset[1] = p_uv_offset.y; + bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP); + + float old_offset[2] = { 0, 0 }; + + for (uint32_t i = p_from_element; i < p_to_element; i++) { + const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; - for (int i = 0; i < p_element_count; i++) { - const RenderList::Element *e = p_elements[i]; + RID material_uniform_set; + ShaderData *shader; + void *mesh_surface; - MaterialData *material = e->material; - ShaderData *shader = material->shader_data; - RID xforms_uniform_set; + if (shadow_pass) { + material_uniform_set = surf->material_uniform_set_shadow; + shader = surf->shader_shadow; + mesh_surface = surf->surface_shadow; + + } else { + material_uniform_set = surf->material_uniform_set; + shader = surf->shader; + mesh_surface = surf->surface; + } + + if (!mesh_surface) { + continue; + } + + if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) { + old_offset[0] = surf->owner->push_constant.lightmap_uv_scale[0]; + old_offset[1] = surf->owner->push_constant.lightmap_uv_scale[1]; + surf->owner->push_constant.lightmap_uv_scale[0] = p_params->uv_offset.x; + surf->owner->push_constant.lightmap_uv_scale[1] = p_params->uv_offset.y; + } //find cull variant ShaderData::CullVariant cull_variant; - if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) { + if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL || p_params->pass_mode == PASS_MODE_SDF || ((p_params->pass_mode == PASS_MODE_SHADOW || p_params->pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) { cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED; } else { - bool mirror = e->instance->mirror; - if (p_reverse_cull) { + bool mirror = surf->owner->mirror; + if (p_params->reverse_cull) { mirror = !mirror; } cull_variant = mirror ? ShaderData::CULL_VARIANT_REVERSED : ShaderData::CULL_VARIANT_NORMAL; } - //find primitive and vertex format - RS::PrimitiveType primitive; - - switch (e->instance->base_type) { - case RS::INSTANCE_MESH: { - primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index); - if (e->instance->skeleton.is_valid()) { - xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET); - } - } break; - case RS::INSTANCE_MULTIMESH: { - RID mesh = storage->multimesh_get_mesh(e->instance->base); - ERR_CONTINUE(!mesh.is_valid()); //should be a bug - primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index); - - xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); - - } break; - case RS::INSTANCE_IMMEDIATE: { - ERR_CONTINUE(true); //should be a bug - } break; - case RS::INSTANCE_PARTICLES: { - RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16); - ERR_CONTINUE(!mesh.is_valid()); //should be a bug - primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index & 0xFFFF); - - xforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); - - } break; - default: { - ERR_CONTINUE(true); //should be a bug - } - } + RS::PrimitiveType primitive = surf->primitive; + RID xforms_uniform_set = surf->owner->transforms_uniform_set; ShaderVersion shader_version = SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. - switch (p_pass_mode) { + switch (p_params->pass_mode) { case PASS_MODE_COLOR: case PASS_MODE_COLOR_TRANSPARENT: { - if (e->uses_lightmap) { + if (surf->sort.uses_lightmap) { shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS; - } else if (e->uses_forward_gi) { + } else if (surf->sort.uses_forward_gi) { shader_version = SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI; } else { shader_version = SHADER_VERSION_COLOR_PASS; } } break; case PASS_MODE_COLOR_SPECULAR: { - if (e->uses_lightmap) { + if (surf->sort.uses_lightmap) { shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR; } else { shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR; @@ -1076,7 +921,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l } break; } - RenderPipelineVertexFormatCacheRD *pipeline = nullptr; + PipelineCacheRD *pipeline = nullptr; pipeline = &shader->pipelines[cull_variant][primitive][shader_version]; @@ -1084,26 +929,37 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l RID vertex_array_rd; RID index_array_rd; - switch (e->instance->base_type) { - case RS::INSTANCE_MESH: { - storage->mesh_surface_get_arrays_and_format(e->instance->base, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format); - } break; - case RS::INSTANCE_MULTIMESH: { - RID mesh = storage->multimesh_get_mesh(e->instance->base); - ERR_CONTINUE(!mesh.is_valid()); //should be a bug - storage->mesh_surface_get_arrays_and_format(mesh, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format); - } break; - case RS::INSTANCE_IMMEDIATE: { - ERR_CONTINUE(true); //should be a bug - } break; - case RS::INSTANCE_PARTICLES: { - RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16); - ERR_CONTINUE(!mesh.is_valid()); //should be a bug - storage->mesh_surface_get_arrays_and_format(mesh, e->surface_index & 0xFFFF, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format); - } break; - default: { - ERR_CONTINUE(true); //should be a bug + //skeleton and blend shape + if (surf->owner->mesh_instance.is_valid()) { + storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + } else { + storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); + } + + if (p_params->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) { + //lod + Vector3 support_min = surf->owner->transformed_aabb.get_support(-p_params->lod_plane.normal); + Vector3 support_max = surf->owner->transformed_aabb.get_support(p_params->lod_plane.normal); + + float distance_min = p_params->lod_plane.distance_to(support_min); + float distance_max = p_params->lod_plane.distance_to(support_max); + + float distance = 0.0; + + if (distance_min * distance_max < 0.0) { + //crossing plane + distance = 0.0; + } else if (distance_min >= 0.0) { + distance = distance_min; + } else if (distance_max <= 0.0) { + distance = -distance_max; } + + index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, surf->owner->lod_model_scale * surf->owner->lod_bias, distance * p_params->lod_distance_multiplier, p_params->screen_lod_threshold); + + } else { + //no lod + index_array_rd = storage->mesh_surface_get_index_array(mesh_surface); } if (prev_vertex_array_rd != vertex_array_rd) { @@ -1118,7 +974,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l prev_index_array_rd = index_array_rd; } - RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_force_wireframe); + RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe); if (pipeline_rd != prev_pipeline_rd) { // checking with prev shader does not make so much sense, as @@ -1132,40 +988,90 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l prev_xforms_uniform_set = xforms_uniform_set; } - if (material != prev_material) { + if (material_uniform_set != prev_material_uniform_set) { //update uniform set - if (material->uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, MATERIAL_UNIFORM_SET); + if (material_uniform_set.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET); } - prev_material = material; + prev_material_uniform_set = material_uniform_set; } - push_constant.index = i; - RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant)); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &surf->owner->push_constant, sizeof(GeometryInstanceForward::PushConstant)); - switch (e->instance->base_type) { - case RS::INSTANCE_MESH: { - RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid()); - } break; - case RS::INSTANCE_MULTIMESH: { - uint32_t instances = storage->multimesh_get_instances_to_draw(e->instance->base); - RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances); - } break; - case RS::INSTANCE_IMMEDIATE: { - } break; - case RS::INSTANCE_PARTICLES: { - uint32_t instances = storage->particles_get_amount(e->instance->base); - RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances); - } break; - default: { - ERR_CONTINUE(true); //should be a bug - } + RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), surf->owner->instance_count); + + if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) { + surf->owner->push_constant.lightmap_uv_scale[0] = old_offset[0]; + surf->owner->push_constant.lightmap_uv_scale[1] = old_offset[1]; } } } -void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) { +void RendererSceneRenderForward::_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) { + //use template for faster performance (pass mode comparisons are inlined) + + switch (p_params->pass_mode) { + case PASS_MODE_COLOR: { + _render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_COLOR_SPECULAR: { + _render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_COLOR_TRANSPARENT: { + _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_SHADOW: { + _render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_SHADOW_DP: { + _render_list_template<PASS_MODE_SHADOW_DP>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_DEPTH: { + _render_list_template<PASS_MODE_DEPTH>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { + _render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: { + _render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_DEPTH_MATERIAL: { + _render_list_template<PASS_MODE_DEPTH_MATERIAL>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + case PASS_MODE_SDF: { + _render_list_template<PASS_MODE_SDF>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); + } break; + } +} + +void RendererSceneRenderForward::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { + uint32_t render_total = p_params->element_count; + uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + uint32_t render_from = p_thread * render_total / total_threads; + uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads); + _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); +} + +void RendererSceneRenderForward::_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, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { + RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer); + p_params->framebuffer_format = fb_format; + + if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time + //multi threaded + thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); + RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RendererSceneRenderForward::_render_list_thread_function, p_params); + RD::get_singleton()->draw_list_end(); + } else { + //single threaded + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); + _render_list(draw_list, fb_format, p_params, 0, p_params->element_count); + RD::get_singleton()->draw_list_end(); + } +} + +void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) { //CameraMatrix projection = p_cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down CameraMatrix correction; @@ -1173,20 +1079,20 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_rende CameraMatrix projection = correction * p_cam_projection; //store camera into ubo - RasterizerStorageRD::store_camera(projection, scene_state.ubo.projection_matrix); - RasterizerStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RasterizerStorageRD::store_transform(p_cam_transform, scene_state.ubo.camera_matrix); - RasterizerStorageRD::store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); + RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix); + RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); + RendererStorageRD::store_transform(p_cam_transform, scene_state.ubo.camera_matrix); + RendererStorageRD::store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); scene_state.ubo.z_far = p_zfar; scene_state.ubo.z_near = p_znear; scene_state.ubo.pancake_shadows = p_pancake_shadows; - RasterizerStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); - RasterizerStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); - RasterizerStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); - RasterizerStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); + RendererStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); + RendererStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); + RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); + RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get(); scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get(); @@ -1214,7 +1120,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_rende scene_state.ubo.fog_enabled = false; if (p_render_buffers.is_valid()) { - RenderBufferDataHighEnd *render_buffers = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + RenderBufferDataForward *render_buffers = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { scene_state.ubo.gi_upscale_for_msaa = true; } @@ -1330,7 +1236,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_rende Basis sky_transform = environment_get_sky_orientation(p_environment); sky_transform = sky_transform.inverse() * p_cam_transform.basis; - RasterizerStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); + RendererStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; @@ -1397,251 +1303,196 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_rende RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true); } -void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) { - RID m_src; - - m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material; - - if (unlikely(get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_DISABLED)) { - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { - m_src = overdraw_material; - } else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING) { - m_src = default_material; - } - } - - MaterialData *material = nullptr; - - if (m_src.is_valid()) { - material = (MaterialData *)storage->material_get_data(m_src, RasterizerStorageRD::SHADER_TYPE_3D); - if (!material || !material->shader_data->valid) { - material = nullptr; - } - } - - if (!material) { - material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - m_src = default_material; - } - - ERR_FAIL_COND(!material); - - _add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index, p_using_sdfgi); - - while (material->next_pass.is_valid()) { - material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D); - if (!material || !material->shader_data->valid) { - break; - } - _add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index, p_using_sdfgi); - } -} - -void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) { - bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; - bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); - bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; - bool has_alpha = has_base_alpha || has_blend_alpha; - - if (p_material->shader_data->uses_sss) { - scene_state.used_sss = true; - } - - if (p_material->shader_data->uses_screen_texture) { - scene_state.used_screen_texture = true; - } - - if (p_material->shader_data->uses_depth_texture) { - scene_state.used_depth_texture = true; - } - - if (p_material->shader_data->uses_normal_texture) { - scene_state.used_normal_texture = true; - } - - if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) { - if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) { - //conditions in which no depth pass should be processed - return; - } - - if ((p_pass_mode != PASS_MODE_DEPTH_MATERIAL && p_pass_mode != PASS_MODE_SDF) && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { - //shader does not use discard and does not write a vertex position, use generic material - if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_DEPTH) { - p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - } else if ((p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) { - p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - } - } - - has_alpha = false; - } - - has_alpha = has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED; - - RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); - - if (!e) { - return; - } - - e->instance = p_instance; - e->material = p_material; - e->surface_index = p_surface; - e->sort_key = 0; - - if (e->material->last_pass != render_pass) { - if (!RD::get_singleton()->uniform_set_is_valid(e->material->uniform_set)) { - //uniform set no longer valid, probably a texture changed - storage->material_force_update_textures(p_material_rid, RasterizerStorageRD::SHADER_TYPE_3D); - } - e->material->last_pass = render_pass; - e->material->index = scene_state.current_material_index++; - if (e->material->shader_data->last_pass != render_pass) { - e->material->shader_data->last_pass = scene_state.current_material_index++; - e->material->shader_data->index = scene_state.current_shader_index++; - } - } - e->geometry_index = p_geometry_index; - e->material_index = e->material->index; - e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH; - e->uses_lightmap = e->instance->lightmap != nullptr || !e->instance->lightmap_sh.empty(); - e->uses_forward_gi = has_alpha && (e->instance->gi_probe_instances.size() || p_using_sdfgi); - e->shader_index = e->shader_index; - e->depth_layer = e->instance->depth_layer; - e->priority = p_material->priority; - - if (p_material->shader_data->uses_time) { - RenderingServerRaster::redraw_request(); - } -} - -void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi) { - scene_state.current_shader_index = 0; - scene_state.current_material_index = 0; +void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi) { scene_state.used_sss = false; scene_state.used_screen_texture = false; scene_state.used_normal_texture = false; scene_state.used_depth_texture = false; - uint32_t geometry_index = 0; + Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(Vector3::AXIS_Z)); + near_plane.d += p_cam_projection.get_z_near(); + float z_max = p_cam_projection.get_z_far() - p_cam_projection.get_z_near(); + uint32_t lightmap_captures_used = 0; + + _update_dirty_geometry_instances(); + render_list.clear(); //fill list - for (int i = 0; i < p_cull_count; i++) { - InstanceBase *inst = p_cull_result[i]; + for (int i = 0; i < (int)p_instances.size(); i++) { + GeometryInstanceForward *inst = static_cast<GeometryInstanceForward *>(p_instances[i]); - //add geometry for drawing - switch (inst->base_type) { - case RS::INSTANCE_MESH: { - const RID *materials = nullptr; - uint32_t surface_count; + Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); + inst->depth = near_plane.distance_to(support_min); + uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); - materials = storage->mesh_get_surface_count_and_materials(inst->base, surface_count); - if (!materials) { - continue; //nothing to do - } + uint32_t flags = inst->base_flags; //fill flags if appropriate - const RID *inst_materials = inst->materials.ptr(); + bool uses_lightmap = false; + bool uses_gi = false; - for (uint32_t j = 0; j < surface_count; j++) { - RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j]; + if (p_pass_mode == PASS_MODE_COLOR) { + //setup GI - uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index); - _add_geometry(inst, j, material, p_pass_mode, surface_index, p_using_sdfgi); + if (inst->lightmap_instance.is_valid()) { + int32_t lightmap_cull_index = -1; + for (uint32_t j = 0; j < scene_state.lightmaps_used; j++) { + if (scene_state.lightmap_ids[j] == inst->lightmap_instance) { + lightmap_cull_index = j; + break; + } } - - //mesh->last_pass=frame; - - } break; - - case RS::INSTANCE_MULTIMESH: { - if (storage->multimesh_get_instances_to_draw(inst->base) == 0) { - //not visible, 0 instances - continue; + if (lightmap_cull_index >= 0) { + inst->push_constant.gi_offset &= 0xFFFF; + inst->push_constant.gi_offset |= lightmap_cull_index; + flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP; + if (scene_state.lightmap_has_sh[lightmap_cull_index]) { + flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP; + } + uses_lightmap = true; + } else { + inst->push_constant.gi_offset = 0xFFFFFFFF; } - RID mesh = storage->multimesh_get_mesh(inst->base); - if (!mesh.is_valid()) { - continue; + } else if (inst->lightmap_sh) { + if (lightmap_captures_used < scene_state.max_lightmap_captures) { + const Color *src_capture = inst->lightmap_sh->sh; + LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used]; + for (int j = 0; j < 9; j++) { + lcd.sh[j * 4 + 0] = src_capture[j].r; + lcd.sh[j * 4 + 1] = src_capture[j].g; + lcd.sh[j * 4 + 2] = src_capture[j].b; + lcd.sh[j * 4 + 3] = src_capture[j].a; + } + flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE; + inst->push_constant.gi_offset = lightmap_captures_used; + lightmap_captures_used++; + uses_lightmap = true; } - const RID *materials = nullptr; - uint32_t surface_count; - - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); - if (!materials) { - continue; //nothing to do + } else if (!low_end) { + if (p_using_opaque_gi) { + flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS; } - for (uint32_t j = 0; j < surface_count; j++) { - uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(mesh, j, render_pass, &geometry_index); - _add_geometry(inst, j, materials[j], p_pass_mode, surface_index, p_using_sdfgi); - } + if (inst->gi_probes[0].is_valid()) { + uint32_t probe0_index = 0xFFFF; + uint32_t probe1_index = 0xFFFF; - } break; -#if 0 - case RS::INSTANCE_IMMEDIATE: { - RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); - ERR_CONTINUE(!immediate); + for (uint32_t j = 0; j < scene_state.giprobes_used; j++) { + if (scene_state.giprobe_ids[j] == inst->gi_probes[0]) { + probe0_index = j; + } else if (scene_state.giprobe_ids[j] == inst->gi_probes[1]) { + probe1_index = j; + } + } - _add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass); + if (probe0_index == 0xFFFF && probe1_index != 0xFFFF) { + //0 must always exist if a probe exists + SWAP(probe0_index, probe1_index); + } - } break; -#endif - case RS::INSTANCE_PARTICLES: { - int draw_passes = storage->particles_get_draw_passes(inst->base); + inst->push_constant.gi_offset = probe0_index | (probe1_index << 16); + uses_gi = true; + } else { + if (p_using_sdfgi && inst->can_sdfgi) { + flags |= INSTANCE_DATA_FLAG_USE_SDFGI; + uses_gi = true; + } + inst->push_constant.gi_offset = 0xFFFFFFFF; + } + } + } + inst->push_constant.flags = flags; - for (int j = 0; j < draw_passes; j++) { - RID mesh = storage->particles_get_draw_pass_mesh(inst->base, j); - if (!mesh.is_valid()) - continue; + GeometryInstanceSurfaceDataCache *surf = inst->surface_caches; - const RID *materials = nullptr; - uint32_t surface_count; + while (surf) { + surf->sort.uses_forward_gi = 0; + surf->sort.uses_lightmap = 0; - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); - if (!materials) { - continue; //nothing to do + if (p_pass_mode == PASS_MODE_COLOR) { + if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { + render_list.add_element(surf); + } + if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA) { + render_list.add_alpha_element(surf); + if (uses_gi) { + surf->sort.uses_forward_gi = 1; } + } - for (uint32_t k = 0; k < surface_count; k++) { - uint32_t surface_index = storage->mesh_surface_get_particles_render_pass_index(mesh, j, render_pass, &geometry_index); - _add_geometry(inst, (j << 16) | k, materials[j], p_pass_mode, surface_index, p_using_sdfgi); - } + if (uses_lightmap) { + surf->sort.uses_lightmap = 1; } - } break; + if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) { + scene_state.used_sss = true; + } + if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE) { + scene_state.used_screen_texture = true; + } + if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE) { + scene_state.used_normal_texture = true; + } + if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) { + scene_state.used_depth_texture = true; + } - default: { + } else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) { + if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) { + render_list.add_element(surf); + } + } else { + if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { + render_list.add_element(surf); + } } + + surf->sort.depth_layer = depth_layer; + + surf = surf->next; } } + + if (lightmap_captures_used) { + RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true); + } +} + +void RendererSceneRenderForward::_setup_giprobes(const PagedArray<RID> &p_giprobes) { + scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES)); + for (uint32_t i = 0; i < scene_state.giprobes_used; i++) { + scene_state.giprobe_ids[i] = p_giprobes[i]; + } } -void RasterizerSceneHighEndRD::_setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform) { - uint32_t lightmaps_used = 0; - for (int i = 0; i < p_lightmap_cull_count; i++) { +void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) { + scene_state.lightmaps_used = 0; + for (int i = 0; i < (int)p_lightmaps.size(); i++) { if (i >= (int)scene_state.max_lightmaps) { break; } - InstanceBase *lm = p_lightmap_cull_result[i]; - Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis; + RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]); + + Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; to_lm = to_lm.inverse().transposed(); //will transform normals - RasterizerStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); - lm->lightmap_cull_index = i; - lightmaps_used++; + RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); + scene_state.lightmap_ids[i] = p_lightmaps[i]; + scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap); + + scene_state.lightmaps_used++; } - if (lightmaps_used > 0) { - RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * lightmaps_used, scene_state.lightmaps, true); + if (scene_state.lightmaps_used > 0) { + RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps, true); } } -void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) { - RenderBufferDataHighEnd *render_buffer = nullptr; +void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) { + RenderBufferDataForward *render_buffer = nullptr; if (p_render_buffer.is_valid()) { - render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffer); + render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer); } //first of all, make a new render pass @@ -1657,6 +1508,13 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor scene_state.ubo.reflection_multiplier = 1.0; } + float lod_distance_multiplier = p_cam_projection.get_lod_multiplier(); + Plane lod_camera_plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z)); + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { + p_screen_lod_threshold = 0.0; + } + //scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size; Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); @@ -1686,7 +1544,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor opaque_framebuffer = render_buffer->color_fb; - if (p_gi_probe_cull_count > 0) { + if (!low_end && p_gi_probes.size() > 0) { using_giprobe = true; render_buffer->ensure_gi(); } @@ -1753,15 +1611,15 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor ERR_FAIL(); //bug? } - _setup_lightmaps(p_lightmap_cull_result, p_lightmap_cull_count, p_cam_transform); + _setup_lightmaps(p_lightmaps, p_cam_transform); + _setup_giprobes(p_gi_probes); _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) - render_list.clear(); - _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, using_sdfgi); + _fill_render_list(p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi, using_sdfgi || using_giprobe); - bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; + bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; if (using_sss) { using_separate_specular = true; @@ -1769,7 +1627,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor using_separate_specular = true; opaque_specular_framebuffer = render_buffer->color_specular_fb; } - RID radiance_uniform_set; + RID radiance_texture; bool draw_sky = false; bool draw_sky_fog_only = false; @@ -1831,7 +1689,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor RID sky = environment_get_sky(p_environment); if (sky.is_valid()) { _update_sky(p_environment, projection, p_cam_transform); - radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET); + radiance_texture = sky_get_radiance_texture_rd(sky); } else { // do not try to draw sky if invalid draw_sky = false; @@ -1841,27 +1699,23 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor clear_color = p_default_bg_color; } - _setup_view_dependant_uniform_set(p_shadow_atlas, p_reflection_atlas, p_gi_probe_cull_result, p_gi_probe_cull_count); - render_list.sort_by_key(false); - _fill_instances(render_list.elements, render_list.element_count, false, false, using_sdfgi || using_giprobe); - bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION; bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; - bool depth_pre_pass = depth_framebuffer.is_valid(); - RID render_buffers_uniform_set; + bool depth_pre_pass = !low_end && depth_framebuffer.is_valid(); bool using_ssao = depth_pre_pass && p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment); bool continue_depth = false; if (depth_pre_pass) { //depth pre pass RENDER_TIMESTAMP("Render Depth Pre-Pass"); + RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); + bool finish_depth = using_ssao || using_sdfgi || using_giprobe; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID(), get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); - RD::get_singleton()->draw_list_end(); + RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + _render_list_with_threads(&render_list_params, depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear); if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { RENDER_TIMESTAMP("Resolve Depth Pre-Pass"); @@ -1881,19 +1735,15 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor } if (using_sdfgi || using_giprobe) { - _process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probe_cull_result, p_gi_probe_cull_count); - } - - if (p_render_buffer.is_valid()) { - //update the render buffers uniform set in case it changed - _update_render_buffers_uniform_set(p_render_buffer); - render_buffers_uniform_set = render_buffer->uniform_set; + _process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probes); } _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid()); RENDER_TIMESTAMP("Render Opaque Pass"); + RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes, p_lightmaps); + bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss; bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss; @@ -1913,13 +1763,13 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor } RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); - RD::get_singleton()->draw_list_end(); + RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + + _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); if (will_continue_color && using_separate_specular) { // close the specular framebuffer, as it's no longer used - draw_list = RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); + RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); RD::get_singleton()->draw_list_end(); } } @@ -1933,8 +1783,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor dc.set_depth_correction(true); CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - for (int i = 0; i < p_gi_probe_cull_count; i++) { - _debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); + for (int i = 0; i < (int)p_gi_probes.size(); i++) { + _debug_giprobe(p_gi_probes[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); } RD::get_singleton()->draw_list_end(); } @@ -1998,12 +1848,9 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor render_list.sort_by_reverse_depth_and_priority(true); - _fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, using_sdfgi); - { - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); - RD::get_singleton()->draw_list_end(); + RenderListParameters render_list_params(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); } if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { @@ -2011,7 +1858,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor } } -void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &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) { +void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &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, float p_lod_distance_multiplier, float p_screen_lod_threshold) { RENDER_TIMESTAMP("Setup Rendering Shadow"); _update_render_base_uniform_set(); @@ -2022,29 +1869,28 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase ** _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar, false, p_use_pancake); - render_list.clear(); + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { + p_screen_lod_threshold = 0.0; + } PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW; - _fill_render_list(p_cull_result, p_cull_count, pass_mode); + _fill_render_list(p_instances, pass_mode, p_projection, p_transform); - _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); + RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); RENDER_TIMESTAMP("Render Shadow"); render_list.sort_by_key(false); - _fill_instances(render_list.elements, render_list.element_count, true); - { //regular forward for now - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, RID(), RID()); - RD::get_singleton()->draw_list_end(); + RenderListParameters render_list_params(render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold); + _render_list_with_threads(&render_list_params, p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); } } -void RasterizerSceneHighEndRD::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count) { +void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) { RENDER_TIMESTAMP("Setup Render Collider Heightfield"); _update_render_base_uniform_set(); @@ -2055,29 +1901,24 @@ void RasterizerSceneHighEndRD::_render_particle_collider_heightfield(RID p_fb, c _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_cam_projection.get_z_far(), false, false); - render_list.clear(); - PassMode pass_mode = PASS_MODE_SHADOW; - _fill_render_list(p_cull_result, p_cull_count, pass_mode); + _fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform); - _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); + RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); RENDER_TIMESTAMP("Render Collider Heightield"); render_list.sort_by_key(false); - _fill_instances(render_list.elements, render_list.element_count, true); - { //regular forward for now - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_fb), render_list.elements, render_list.element_count, false, pass_mode, true, RID(), RID()); - RD::get_singleton()->draw_list_end(); + RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, pass_mode, true, rp_uniform_set); + _render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); } } -void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering Material"); _update_render_base_uniform_set(); @@ -2089,20 +1930,17 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); - render_list.clear(); - PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(p_cull_result, p_cull_count, pass_mode); + _fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform); - _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); + RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); RENDER_TIMESTAMP("Render Material"); render_list.sort_by_key(false); - _fill_instances(render_list.elements, render_list.element_count, true); - { + RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set); //regular forward for now Vector<Color> clear; clear.push_back(Color(0, 0, 0, 0)); @@ -2111,12 +1949,12 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform clear.push_back(Color(0, 0, 0, 0)); clear.push_back(Color(0, 0, 0, 0)); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID()); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); RD::get_singleton()->draw_list_end(); } } -void RasterizerSceneHighEndRD::_render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { RENDER_TIMESTAMP("Setup Rendering UV2"); _update_render_base_uniform_set(); @@ -2128,20 +1966,17 @@ void RasterizerSceneHighEndRD::_render_uv2(InstanceBase **p_cull_result, int p_c _setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); - render_list.clear(); - PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(p_cull_result, p_cull_count, pass_mode); + _fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform()); - _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); + RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); RENDER_TIMESTAMP("Render Material"); render_list.sort_by_key(false); - _fill_instances(render_list.elements, render_list.element_count, true); - { + RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, true); //regular forward for now Vector<Color> clear; clear.push_back(Color(0, 0, 0, 0)); @@ -2169,69 +2004,35 @@ void RasterizerSceneHighEndRD::_render_uv2(InstanceBase **p_cull_result, int p_c Vector2 ofs = uv_offsets[i]; ofs.x /= p_region.size.width; ofs.y /= p_region.size.height; - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID(), true, ofs); //first wireframe, for pseudo conservative + render_list_params.uv_offset = ofs; + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); //first wireframe, for pseudo conservative } - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID(), false); //second regular triangles + render_list_params.uv_offset = Vector2(); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); //second regular triangles RD::get_singleton()->draw_list_end(); } } -void RasterizerSceneHighEndRD::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { +void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { RENDER_TIMESTAMP("Render SDFGI"); _update_render_base_uniform_set(); - RenderBufferDataHighEnd *render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); ERR_FAIL_COND(!render_buffer); render_pass++; - render_list.clear(); PassMode pass_mode = PASS_MODE_SDF; - _fill_render_list(p_cull_result, p_cull_count, pass_mode); + _fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform()); render_list.sort_by_key(false); - _fill_instances(render_list.elements, render_list.element_count, true); - _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); + RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture); Vector3 half_extents = p_bounds.size * 0.5; Vector3 center = p_bounds.position + half_extents; - if (render_buffer->render_sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_buffer->render_sdfgi_uniform_set)) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.ids.push_back(p_albedo_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 1; - u.ids.push_back(p_emission_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 2; - u.ids.push_back(p_emission_aniso_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 3; - u.ids.push_back(p_geom_facing_texture); - uniforms.push_back(u); - } - - render_buffer->render_sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_sdfgi_rd, RENDER_BUFFERS_UNIFORM_SET); - } - Vector<RID> sbs; sbs.push_back(p_albedo_texture); sbs.push_back(p_emission_texture); @@ -2276,7 +2077,7 @@ void RasterizerSceneHighEndRD::_render_sdfgi(RID p_render_buffers, const Vector3 to_bounds.origin = p_bounds.position; to_bounds.basis.scale(p_bounds.size); - RasterizerStorageRD::store_transform(to_bounds.affine_inverse() * cam_xform, scene_state.ubo.sdf_to_bounds); + RendererStorageRD::store_transform(to_bounds.affine_inverse() * cam_xform, scene_state.ubo.sdf_to_bounds); _setup_environment(RID(), RID(), camera_proj, cam_xform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); @@ -2286,20 +2087,19 @@ void RasterizerSceneHighEndRD::_render_sdfgi(RID p_render_buffers, const Vector3 E = sdfgi_framebuffer_size_cache.insert(fb_size, fb); } - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(E->get()), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), render_buffer->render_sdfgi_uniform_set, false); //second regular triangles - RD::get_singleton()->draw_list_end(); + RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false); + _render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); } } -void RasterizerSceneHighEndRD::_base_uniforms_changed() { +void RendererSceneRenderForward::_base_uniforms_changed() { if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } render_base_uniform_set = RID(); } -void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { +void RendererSceneRenderForward::_update_render_base_uniform_set() { if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) { if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); @@ -2311,7 +2111,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 1; u.ids.resize(12); RID *ids_ptr = u.ids.ptrw(); @@ -2333,7 +2133,7 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { { RD::Uniform u; u.binding = 2; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.ids.push_back(shadow_sampler); uniforms.push_back(u); } @@ -2341,22 +2141,15 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { { RD::Uniform u; u.binding = 3; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.ids.push_back(scene_state.uniform_buffer); uniforms.push_back(u); } - { - RD::Uniform u; - u.binding = 4; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(scene_state.instance_buffer); - uniforms.push_back(u); - } { RD::Uniform u; u.binding = 5; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(get_positional_light_buffer()); uniforms.push_back(u); } @@ -2364,101 +2157,94 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { { RD::Uniform u; u.binding = 6; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(get_reflection_probe_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 7; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.ids.push_back(get_directional_light_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 10; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(scene_state.lightmap_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 11; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.ids = storage->lightmap_array_get_textures(); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 12; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(scene_state.lightmap_capture_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 13; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 12; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID decal_atlas = storage->decal_atlas_get_texture(); u.ids.push_back(decal_atlas); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 14; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 13; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID decal_atlas = storage->decal_atlas_get_texture_srgb(); u.ids.push_back(decal_atlas); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 15; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 14; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(get_decal_buffer()); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 16; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 15; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.push_back(get_cluster_builder_texture()); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 17; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 16; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(get_cluster_builder_indices_buffer()); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 18; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 17; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (directional_shadow_get_texture().is_valid()) { u.ids.push_back(directional_shadow_get_texture()); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); } uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 19; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 18; u.ids.push_back(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); } - { + if (!low_end) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 20; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 19; u.ids.push_back(sdfgi_get_ubo()); uniforms.push_back(u); } @@ -2467,9 +2253,14 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { } } -void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) { - if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { - RD::get_singleton()->free(view_dependant_uniform_set); +RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps) { + if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) { + RD::get_singleton()->free(render_pass_uniform_set); + } + + RenderBufferDataForward *rb = nullptr; + if (p_render_buffers.is_valid()) { + rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); } //default render buffer and scene state uniform set @@ -2477,211 +2268,868 @@ void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_at Vector<RD::Uniform> uniforms; { - RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); + RID radiance_texture; + if (p_radiance_texture.is_valid()) { + radiance_texture = p_radiance_texture; + } else { + radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + } RD::Uniform u; u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(radiance_texture); + uniforms.push_back(u); + } + + { + RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (ref_texture.is_valid()) { u.ids.push_back(ref_texture); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); } uniforms.push_back(u); } { RD::Uniform u; - u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture; if (p_shadow_atlas.is_valid()) { texture = shadow_atlas_get_texture(p_shadow_atlas); } if (!texture.is_valid()) { - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); } u.ids.push_back(texture); uniforms.push_back(u); } + { + RD::Uniform u; + u.binding = 3; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.resize(scene_state.max_lightmaps); + RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { + if (i < p_lightmaps.size()) { + RID base = lightmap_instance_get_lightmap(p_lightmaps[i]); + RID texture = storage->lightmap_get_texture(base); + RID rd_texture = storage->texture_get_rd_texture(texture); + u.ids.write[i] = rd_texture; + } else { + u.ids.write[i] = default_tex; + } + } + uniforms.push_back(u); + } { RD::Uniform u; - u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID default_tex = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + u.binding = 4; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.resize(MAX_GI_PROBES); + RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_GI_PROBES; i++) { - if (i < p_gi_probe_cull_count) { - RID tex = gi_probe_instance_get_texture(p_gi_probe_cull_result[i]); + if (i < (int)p_gi_probes.size()) { + RID tex = gi_probe_instance_get_texture(p_gi_probes[i]); if (!tex.is_valid()) { tex = default_tex; } - u.ids.push_back(tex); + u.ids.write[i] = tex; } else { - u.ids.push_back(default_tex); + u.ids.write[i] = default_tex; } } uniforms.push_back(u); } - view_dependant_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, VIEW_DEPENDANT_UNIFORM_SET); -} -void RasterizerSceneHighEndRD::_render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb) { - if (!rb->uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { - RD::get_singleton()->free(rb->uniform_set); + { + RD::Uniform u; + u.binding = 5; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + u.ids.push_back(texture); + uniforms.push_back(u); } - rb->uniform_set = RID(); -} - -void RasterizerSceneHighEndRD::_render_buffers_uniform_set_changed(RID p_render_buffers) { - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - _render_buffers_clear_uniform_set(rb); -} - -RID RasterizerSceneHighEndRD::_render_buffers_get_normal_texture(RID p_render_buffers) { - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - return rb->normal_roughness_buffer; -} - -RID RasterizerSceneHighEndRD::_render_buffers_get_ambient_texture(RID p_render_buffers) { - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - return rb->ambient_buffer; -} - -RID RasterizerSceneHighEndRD::_render_buffers_get_reflection_texture(RID p_render_buffers) { - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - return rb->reflection_buffer; -} - -void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_buffers) { - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - if (rb->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = false && rb->depth.is_valid() ? rb->depth : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - u.ids.push_back(texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID bbt = render_buffers_get_back_buffer_texture(p_render_buffers); - RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - } + { + RD::Uniform u; + u.binding = 6; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_buffers) : RID(); + RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + if (!low_end) { { RD::Uniform u; - u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + u.binding = 7; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL); u.ids.push_back(texture); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 4; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID aot = render_buffers_get_ao_texture(p_render_buffers); - RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.binding = 8; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID aot = rb ? render_buffers_get_ao_texture(p_render_buffers) : RID(); + RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 5; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.binding = 9; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb && rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 6; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.binding = 10; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb && rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 7; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 11; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID t; - if (render_buffers_is_sdfgi_enabled(p_render_buffers)) { + if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) { t = render_buffers_get_sdfgi_irradiance_probes(p_render_buffers); } else { - t = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } u.ids.push_back(t); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 8; - u.type = RD::UNIFORM_TYPE_TEXTURE; - if (render_buffers_is_sdfgi_enabled(p_render_buffers)) { + u.binding = 12; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) { u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers)); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } { RD::Uniform u; - u.binding = 9; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(render_buffers_get_gi_probe_buffer(p_render_buffers)); + u.binding = 13; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_buffers) : render_buffers_get_default_gi_probe_buffer()); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 10; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 14; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID vfog = RID(); - if (p_render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_buffers)) { + if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) { vfog = render_buffers_get_volumetric_fog_texture(p_render_buffers); if (vfog.is_null()) { - vfog = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); } } else { - vfog = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); } u.ids.push_back(vfog); uniforms.push_back(u); } - rb->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); } + + render_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_PASS_UNIFORM_SET); + return render_pass_uniform_set; } -RasterizerSceneHighEndRD *RasterizerSceneHighEndRD::singleton = nullptr; +RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) { + if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) { + RD::get_singleton()->free(sdfgi_pass_uniform_set); + } + + Vector<RD::Uniform> uniforms; + + { + // No radiance texture. + RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(radiance_texture); + uniforms.push_back(u); + } + + { + // No reflection atlas. + RID ref_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(ref_texture); + uniforms.push_back(u); + } + + { + // No shadow atlas. + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + { + // No Lightmaps + RD::Uniform u; + u.binding = 3; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.resize(scene_state.max_lightmaps); + RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { + u.ids.write[i] = default_tex; + } + + uniforms.push_back(u); + } -void RasterizerSceneHighEndRD::set_time(double p_time, double p_step) { + { + // No GIProbes + RD::Uniform u; + u.binding = 4; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.resize(MAX_GI_PROBES); + RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + for (int i = 0; i < MAX_GI_PROBES; i++) { + u.ids.write[i] = default_tex; + } + + uniforms.push_back(u); + } + // actual sdfgi stuff + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(p_albedo_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 6; + u.ids.push_back(p_emission_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 7; + u.ids.push_back(p_emission_aniso_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 8; + u.ids.push_back(p_geom_facing_texture); + uniforms.push_back(u); + } + + sdfgi_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET); + return sdfgi_pass_uniform_set; +} + +void RendererSceneRenderForward::_render_buffers_clear_uniform_set(RenderBufferDataForward *rb) { +} + +void RendererSceneRenderForward::_render_buffers_uniform_set_changed(RID p_render_buffers) { + RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + + _render_buffers_clear_uniform_set(rb); +} + +RID RendererSceneRenderForward::_render_buffers_get_normal_texture(RID p_render_buffers) { + RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + + return rb->normal_roughness_buffer; +} + +RID RendererSceneRenderForward::_render_buffers_get_ambient_texture(RID p_render_buffers) { + RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + + return rb->ambient_buffer; +} + +RID RendererSceneRenderForward::_render_buffers_get_reflection_texture(RID p_render_buffers) { + RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + + return rb->reflection_buffer; +} + +RendererSceneRenderForward *RendererSceneRenderForward::singleton = nullptr; + +void RendererSceneRenderForward::set_time(double p_time, double p_step) { time = p_time; - RasterizerSceneRD::set_time(p_time, p_step); + RendererSceneRenderRD::set_time(p_time, p_step); +} + +void RendererSceneRenderForward::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + if (ginstance->dirty_list_element.in_list()) { + return; + } + + //clear surface caches + GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches; + + while (surf) { + GeometryInstanceSurfaceDataCache *next = surf->next; + geometry_instance_surface_alloc.free(surf); + surf = next; + } + + ginstance->surface_caches = nullptr; + + geometry_instance_dirty_list.add(&ginstance->dirty_list_element); +} + +void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { + bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; + bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); + bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; + bool has_alpha = has_base_alpha || has_blend_alpha; + + uint32_t flags = 0; + + if (p_material->shader_data->uses_sss) { + flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING; + } + + if (p_material->shader_data->uses_screen_texture) { + flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE; + } + + if (p_material->shader_data->uses_depth_texture) { + flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE; + } + + if (p_material->shader_data->uses_normal_texture) { + flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE; + } + + if (ginstance->data->cast_double_sided_shaodows) { + flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS; + } + + if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) { + //material is only meant for alpha pass + flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA; + if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED)) { + flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; + flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; + } + } else { + flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE; + flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; + flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; + } + + MaterialData *material_shadow = nullptr; + //void *surface_shadow = nullptr; + if (!p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { + flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; + material_shadow = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); + } else { + material_shadow = p_material; + } + + GeometryInstanceSurfaceDataCache *sdcache = geometry_instance_surface_alloc.alloc(); + + sdcache->flags = flags; + + sdcache->shader = p_material->shader_data; + sdcache->material_uniform_set = p_material->uniform_set; + sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface); + sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface); + sdcache->surface_index = p_surface; + + if (ginstance->data->dirty_dependencies) { + storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); + } + + //shadow + sdcache->shader_shadow = material_shadow->shader_data; + sdcache->material_uniform_set_shadow = material_shadow->uniform_set; + sdcache->surface_shadow = sdcache->surface; //when adding special shadow meshes, will use this + + sdcache->owner = ginstance; + + sdcache->next = ginstance->surface_caches; + ginstance->surface_caches = sdcache; + + //sortkey + + sdcache->sort.sort_key1 = 0; + sdcache->sort.sort_key2 = 0; + + sdcache->sort.surface_type = ginstance->data->base_type; + sdcache->sort.material_id = p_material_id; + sdcache->sort.shader_id = p_shader_id; + sdcache->sort.geometry_id = p_mesh.get_local_index(); + sdcache->sort.uses_forward_gi = ginstance->can_sdfgi; + sdcache->sort.priority = p_material->priority; +} + +void RendererSceneRenderForward::_geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { + RID m_src; + + m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; + + MaterialData *material = nullptr; + + if (m_src.is_valid()) { + material = (MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); + if (!material || !material->shader_data->valid) { + material = nullptr; + } + } + + if (material) { + if (ginstance->data->dirty_dependencies) { + storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); + } + } else { + material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); + m_src = default_material; + } + + ERR_FAIL_COND(!material); + + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, m_src.get_local_index(), storage->material_get_shader_id(m_src), p_mesh); + + while (material->next_pass.is_valid()) { + RID next_pass = material->next_pass; + material = (MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); + if (!material || !material->shader_data->valid) { + break; + } + if (ginstance->data->dirty_dependencies) { + storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); + } + _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); + } +} + +void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_geometry_instance) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + + if (ginstance->data->dirty_dependencies) { + ginstance->data->dependency_tracker.update_begin(); + } + + //add geometry for drawing + switch (ginstance->data->base_type) { + case RS::INSTANCE_MESH: { + const RID *materials = nullptr; + uint32_t surface_count; + RID mesh = ginstance->data->base; + + materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + if (materials) { + //if no materials, no surfaces. + const RID *inst_materials = ginstance->data->surface_materials.ptr(); + uint32_t surf_mat_count = ginstance->data->surface_materials.size(); + + for (uint32_t j = 0; j < surface_count; j++) { + RID material = (j < surf_mat_count && inst_materials[j].is_valid()) ? inst_materials[j] : materials[j]; + _geometry_instance_add_surface(ginstance, j, material, mesh); + } + } + + ginstance->instance_count = 1; + + } break; + + case RS::INSTANCE_MULTIMESH: { + RID mesh = storage->multimesh_get_mesh(ginstance->data->base); + if (mesh.is_valid()) { + const RID *materials = nullptr; + uint32_t surface_count; + + materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + if (materials) { + for (uint32_t j = 0; j < surface_count; j++) { + _geometry_instance_add_surface(ginstance, j, materials[j], mesh); + } + } + + ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base); + } + + } break; +#if 0 + case RS::INSTANCE_IMMEDIATE: { + RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); + ERR_CONTINUE(!immediate); + + _add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass); + + } break; +#endif + case RS::INSTANCE_PARTICLES: { + int draw_passes = storage->particles_get_draw_passes(ginstance->data->base); + + for (int j = 0; j < draw_passes; j++) { + RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j); + if (!mesh.is_valid()) + continue; + + const RID *materials = nullptr; + uint32_t surface_count; + + materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + if (materials) { + for (uint32_t k = 0; k < surface_count; k++) { + _geometry_instance_add_surface(ginstance, k, materials[k], mesh); + } + } + } + + ginstance->instance_count = storage->particles_get_amount(ginstance->data->base); + + } break; + + default: { + } + } + + //Fill push constant + + ginstance->push_constant.instance_uniforms_ofs = ginstance->data->shader_parameters_offset >= 0 ? ginstance->data->shader_parameters_offset : 0; + ginstance->push_constant.layer_mask = ginstance->data->layer_mask; + ginstance->push_constant.flags = 0; + ginstance->push_constant.gi_offset = 0xFFFFFFFF; //disabled + + bool store_transform = true; + + if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; + uint32_t stride; + if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; + stride = 2; + } else { + stride = 3; + } + if (storage->multimesh_uses_colors(ginstance->data->base)) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; + stride += 1; + } + if (storage->multimesh_uses_custom_data(ginstance->data->base)) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; + stride += 1; + } + + ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); + ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); + + } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; + uint32_t stride; + if (false) { // 2D particles + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; + stride = 2; + } else { + stride = 3; + } + + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; + stride += 1; + + ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; + stride += 1; + + ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); + + if (!storage->particles_is_using_local_coords(ginstance->data->base)) { + store_transform = false; + } + ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); + + } else if (ginstance->data->base_type == RS::INSTANCE_MESH) { + if (storage->skeleton_is_valid(ginstance->data->skeleton)) { + ginstance->base_flags |= INSTANCE_DATA_FLAG_SKELETON; + ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET); + if (ginstance->data->dirty_dependencies) { + storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); + } + } + } + + if (store_transform) { + RendererStorageRD::store_transform(ginstance->data->transform, ginstance->push_constant.transform); + } else { + RendererStorageRD::store_transform(Transform(), ginstance->push_constant.transform); + } + + ginstance->can_sdfgi = false; + + if (lightmap_instance_is_valid(ginstance->lightmap_instance)) { + ginstance->push_constant.gi_offset = ginstance->data->lightmap_slice_index << 16; + ginstance->push_constant.lightmap_uv_scale[0] = ginstance->data->lightmap_uv_scale.position.x; + ginstance->push_constant.lightmap_uv_scale[1] = ginstance->data->lightmap_uv_scale.position.y; + ginstance->push_constant.lightmap_uv_scale[2] = ginstance->data->lightmap_uv_scale.size.width; + ginstance->push_constant.lightmap_uv_scale[3] = ginstance->data->lightmap_uv_scale.size.height; + } else if (!low_end) { + if (ginstance->gi_probes[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) { + ginstance->can_sdfgi = true; + } + } + + if (ginstance->data->dirty_dependencies) { + ginstance->data->dependency_tracker.update_end(); + ginstance->data->dirty_dependencies = false; + } + + ginstance->dirty_list_element.remove_from_list(); +} + +void RendererSceneRenderForward::_update_dirty_geometry_instances() { + while (geometry_instance_dirty_list.first()) { + _geometry_instance_update(geometry_instance_dirty_list.first()->self()); + } +} + +void RendererSceneRenderForward::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { + switch (p_notification) { + case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: + case RendererStorage::DEPENDENCY_CHANGED_MESH: + case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: + case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: { + static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); + } break; + case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_tracker->userdata); + if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { + ginstance->instance_count = static_cast<RendererSceneRenderForward *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); + } + } break; + default: { + //rest of notifications of no interest + } break; + } +} +void RendererSceneRenderForward::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { + static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } -RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage) : - RasterizerSceneRD(p_storage) { +RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_instance_create(RID p_base) { + RS::InstanceType type = storage->get_base_type(p_base); + ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); + + GeometryInstanceForward *ginstance = geometry_instance_alloc.alloc(); + ginstance->data = memnew(GeometryInstanceForward::Data); + + ginstance->data->base = p_base; + ginstance->data->base_type = type; + ginstance->data->dependency_tracker.userdata = ginstance; + ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed; + ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted; + + _geometry_instance_mark_dirty(ginstance); + + return ginstance; +} +void RendererSceneRenderForward::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->skeleton = p_skeleton; + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; +} +void RendererSceneRenderForward::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->material_override = p_override; + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; +} +void RendererSceneRenderForward::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->surface_materials = p_materials; + _geometry_instance_mark_dirty(ginstance); + ginstance->data->dirty_dependencies = true; +} +void RendererSceneRenderForward::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->mesh_instance = p_mesh_instance; + _geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + RendererStorageRD::store_transform(p_transform, ginstance->push_constant.transform); + ginstance->data->transform = p_transform; + ginstance->mirror = p_transform.basis.determinant() < 0; + ginstance->data->aabb = p_aabb; + ginstance->transformed_aabb = p_transformed_aabb; + + Vector3 model_scale_vec = p_transform.basis.get_scale_abs(); + // handle non uniform scale here + + float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); + float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z)); + ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9; + + ginstance->lod_model_scale = max_scale; +} +void RendererSceneRenderForward::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->lod_bias = p_lod_bias; +} +void RendererSceneRenderForward::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->use_baked_light = p_enable; + _geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->use_dynamic_gi = p_enable; + _geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->lightmap_instance = p_lightmap_instance; + ginstance->data->lightmap_uv_scale = p_lightmap_uv_scale; + ginstance->data->lightmap_slice_index = p_lightmap_slice_index; + _geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + if (p_sh9) { + if (ginstance->lightmap_sh == nullptr) { + ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc(); + } + + copymem(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9); + } else { + if (ginstance->lightmap_sh != nullptr) { + geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); + ginstance->lightmap_sh = nullptr; + } + } + _geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->shader_parameters_offset = p_offset; + _geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + + ginstance->data->cast_double_sided_shaodows = p_enable; + _geometry_instance_mark_dirty(ginstance); +} + +void RendererSceneRenderForward::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + ginstance->data->layer_mask = p_layer_mask; + ginstance->push_constant.layer_mask = p_layer_mask; +} + +void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geometry_instance) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + if (ginstance->lightmap_sh != nullptr) { + geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); + } + GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches; + while (surf) { + GeometryInstanceSurfaceDataCache *next = surf->next; + geometry_instance_surface_alloc.free(surf); + surf = next; + } + memdelete(ginstance->data); + geometry_instance_alloc.free(ginstance); +} + +uint32_t RendererSceneRenderForward::geometry_instance_get_pair_mask() { + return (1 << RS::INSTANCE_GI_PROBE); +} +void RendererSceneRenderForward::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { +} +void RendererSceneRenderForward::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { +} +void RendererSceneRenderForward::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { +} + +Transform RendererSceneRenderForward::geometry_instance_get_transform(GeometryInstance *p_instance) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance); + ERR_FAIL_COND_V(!ginstance, Transform()); + return ginstance->data->transform; +} +AABB RendererSceneRenderForward::geometry_instance_get_aabb(GeometryInstance *p_instance) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance); + ERR_FAIL_COND_V(!ginstance, AABB()); + return ginstance->data->aabb; +} + +void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) { + GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + ERR_FAIL_COND(!ginstance); + if (p_gi_probe_instance_count > 0) { + ginstance->gi_probes[0] = p_gi_probe_instances[0]; + } else { + ginstance->gi_probes[0] = RID(); + } + + if (p_gi_probe_instance_count > 1) { + ginstance->gi_probes[1] = p_gi_probe_instances[1]; + } else { + ginstance->gi_probes[1] = RID(); + } +} + +RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) : + RendererSceneRenderRD(p_storage) { singleton = this; + low_end = is_low_end(); storage = p_storage; /* SCENE SHADER */ { String defines; + if (low_end) { + defines += "\n#define LOW_END_MODE \n"; + } + defines += "\n#define MAX_ROUGHNESS_LOD " + itos(get_roughness_layers() - 1) + ".0\n"; if (is_using_radiance_cubemap_array()) { defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; @@ -2691,11 +3139,10 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag { //lightmaps - scene_state.max_lightmaps = storage->lightmap_array_get_size(); + scene_state.max_lightmaps = low_end ? 2 : MAX_LIGHTMAPS; defines += "\n#define MAX_LIGHTMAP_TEXTURES " + itos(scene_state.max_lightmaps) + "\n"; defines += "\n#define MAX_LIGHTMAPS " + itos(scene_state.max_lightmaps) + "\n"; - scene_state.lightmaps = memnew_arr(LightmapData, scene_state.max_lightmaps); scene_state.lightmap_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapData) * scene_state.max_lightmaps); } { @@ -2721,10 +3168,20 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag shader_versions.push_back("\n#define USE_LIGHTMAP\n"); shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); shader.scene_shader.initialize(shader_versions, defines); + + if (is_low_end()) { + //disable the high end versions + shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, false); + shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, false); + shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_SDF, false); + shader.scene_shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, false); + shader.scene_shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, false); + shader.scene_shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, false); + } } - storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_3D, _create_shader_funcs); - storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_3D, _create_material_funcs); + storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); + storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs); { //shader compiler @@ -2762,8 +3219,8 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.renames["FRAGCOORD"] = "gl_FragCoord"; actions.renames["FRONT_FACING"] = "gl_FrontFacing"; - actions.renames["NORMALMAP"] = "normalmap"; - actions.renames["NORMALMAP_DEPTH"] = "normaldepth"; + actions.renames["NORMAL_MAP"] = "normal_map"; + actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; actions.renames["ALBEDO"] = "albedo"; actions.renames["ALPHA"] = "alpha"; actions.renames["METALLIC"] = "metallic"; @@ -2795,6 +3252,12 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.renames["FOG"] = "custom_fog"; actions.renames["RADIANCE"] = "custom_radiance"; actions.renames["IRRADIANCE"] = "custom_irradiance"; + actions.renames["BONE_INDICES"] = "bone_attrib"; + actions.renames["BONE_WEIGHTS"] = "weight_attrib"; + actions.renames["CUSTOM0"] = "custom0_attrib"; + actions.renames["CUSTOM1"] = "custom1_attrib"; + actions.renames["CUSTOM2"] = "custom2_attrib"; + actions.renames["CUSTOM3"] = "custom3_attrib"; //for light actions.renames["VIEW"] = "view"; @@ -2805,6 +3268,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; actions.renames["SPECULAR_LIGHT"] = "specular_light"; + actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n"; actions.usage_defines["BINORMAL"] = "@TANGENT"; actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n"; @@ -2817,8 +3281,14 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n"; actions.usage_defines["UV"] = "#define UV_USED\n"; actions.usage_defines["UV2"] = "#define UV2_USED\n"; - actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; - actions.usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; + actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n"; + actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n"; + actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n"; + actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n"; + actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n"; + actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n"; + actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n"; + actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; @@ -2885,7 +3355,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; actions.global_buffer_array_variable = "global_variables.data"; - actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs"; + actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs"; shader.compiler.initialize(actions); } @@ -2895,12 +3365,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag render_list.init(); render_pass = 0; - { - scene_state.max_instances = render_list.max_elements; - scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances); - scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances); - } - scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); { @@ -2910,9 +3374,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag default_material = storage->material_create(); storage->material_set_shader(default_material, default_shader); - MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); + MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); - default_shader_sdfgi_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); + if (!low_end) { + default_shader_sdfgi_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); + } } { @@ -2931,7 +3397,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256); Vector<RD::Uniform> uniforms; RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(default_vec4_xform_buffer); u.binding = 0; uniforms.push_back(u); @@ -2947,73 +3413,21 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag shadow_sampler = RD::get_singleton()->sampler_create(sampler); } - { - Vector<RD::Uniform> uniforms; - - RD::Uniform u; - u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - - default_radiance_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RADIANCE_UNIFORM_SET); - } - - { //render buffers - Vector<RD::Uniform> uniforms; - for (int i = 0; i < 7; i++) { - RD::Uniform u; - u.binding = i; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(i == 0 ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE : (i == 2 ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL : RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); - u.ids.push_back(texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 7; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); - u.ids.push_back(texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 8; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 9; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(render_buffers_get_default_gi_probe_buffer()); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 10; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); - uniforms.push_back(u); - } - - default_render_buffers_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); - } + render_list_thread_threshold = GLOBAL_GET("rendering/forward_renderer/threaded_render_minimum_instances"); } -RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() { +RendererSceneRenderForward::~RendererSceneRenderForward() { directional_shadow_atlas_set_size(0); //clear base uniform set if still valid - if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { - RD::get_singleton()->free(view_dependant_uniform_set); + if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) { + RD::get_singleton()->free(render_pass_uniform_set); + } + + if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) { + RD::get_singleton()->free(sdfgi_pass_uniform_set); } - RD::get_singleton()->free(default_render_buffers_uniform_set); - RD::get_singleton()->free(default_radiance_uniform_set); RD::get_singleton()->free(default_vec4_xform_buffer); RD::get_singleton()->free(shadow_sampler); @@ -3027,11 +3441,8 @@ RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() { { RD::get_singleton()->free(scene_state.uniform_buffer); - RD::get_singleton()->free(scene_state.instance_buffer); RD::get_singleton()->free(scene_state.lightmap_buffer); RD::get_singleton()->free(scene_state.lightmap_capture_buffer); - memdelete_arr(scene_state.instances); - memdelete_arr(scene_state.lightmaps); memdelete_arr(scene_state.lightmap_captures); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.h b/servers/rendering/renderer_rd/renderer_scene_render_forward.h new file mode 100644 index 0000000000..3b5a5ad96f --- /dev/null +++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.h @@ -0,0 +1,745 @@ +/*************************************************************************/ +/* renderer_scene_render_forward.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RENDERING_SERVER_SCENE_RENDER_FORWARD_H +#define RENDERING_SERVER_SCENE_RENDER_FORWARD_H + +#include "core/templates/paged_allocator.h" +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" +#include "servers/rendering/renderer_rd/shaders/scene_forward.glsl.gen.h" + +class RendererSceneRenderForward : public RendererSceneRenderRD { + enum { + SCENE_UNIFORM_SET = 0, + RENDER_PASS_UNIFORM_SET = 1, + TRANSFORMS_UNIFORM_SET = 2, + MATERIAL_UNIFORM_SET = 3 + }; + + enum { + SDFGI_MAX_CASCADES = 8, + MAX_GI_PROBES = 8, + MAX_LIGHTMAPS = 8, + MAX_GI_PROBES_PER_INSTANCE = 2, + }; + + /* Scene Shader */ + + enum ShaderVersion { + SHADER_VERSION_DEPTH_PASS, + SHADER_VERSION_DEPTH_PASS_DP, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, + SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, + SHADER_VERSION_DEPTH_PASS_WITH_SDF, + SHADER_VERSION_COLOR_PASS, + SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, + SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, + SHADER_VERSION_LIGHTMAP_COLOR_PASS, + SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, + SHADER_VERSION_MAX + }; + + struct { + SceneForwardShaderRD scene_shader; + ShaderCompilerRD compiler; + } shader; + + RendererStorageRD *storage; + + /* Material */ + + struct ShaderData : public RendererStorageRD::ShaderData { + enum BlendMode { //used internally + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + BLEND_MODE_ALPHA_TO_COVERAGE + }; + + enum DepthDraw { + DEPTH_DRAW_DISABLED, + DEPTH_DRAW_OPAQUE, + DEPTH_DRAW_ALWAYS + }; + + enum DepthTest { + DEPTH_TEST_DISABLED, + DEPTH_TEST_ENABLED + }; + + enum Cull { + CULL_DISABLED, + CULL_FRONT, + CULL_BACK + }; + + enum CullVariant { + CULL_VARIANT_NORMAL, + CULL_VARIANT_REVERSED, + CULL_VARIANT_DOUBLE_SIDED, + CULL_VARIANT_MAX + + }; + + enum AlphaAntiAliasing { + ALPHA_ANTIALIASING_OFF, + ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE, + ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE + }; + + bool valid; + RID version; + uint32_t vertex_input_mask; + PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; + + String path; + + Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms; + + Vector<uint32_t> ubo_offsets; + uint32_t ubo_size; + + String code; + Map<StringName, RID> default_texture_params; + + DepthDraw depth_draw; + DepthTest depth_test; + + bool uses_point_size; + bool uses_alpha; + bool uses_blend_alpha; + bool uses_alpha_clip; + bool uses_depth_pre_pass; + bool uses_discard; + bool uses_roughness; + bool uses_normal; + + bool unshaded; + bool uses_vertex; + bool uses_sss; + bool uses_transmittance; + bool uses_screen_texture; + bool uses_depth_texture; + bool uses_normal_texture; + bool uses_time; + bool writes_modelview_or_projection; + bool uses_world_coordinates; + + uint64_t last_pass = 0; + uint32_t index = 0; + + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void get_param_list(List<PropertyInfo> *p_param_list) const; + void get_instance_param_list(List<RendererStorage::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; + + ShaderData(); + virtual ~ShaderData(); + }; + + RendererStorageRD::ShaderData *_create_shader_func(); + static RendererStorageRD::ShaderData *_create_shader_funcs() { + return static_cast<RendererSceneRenderForward *>(singleton)->_create_shader_func(); + } + + struct MaterialData : public RendererStorageRD::MaterialData { + uint64_t last_frame; + ShaderData *shader_data; + RID uniform_buffer; + RID uniform_set; + Vector<RID> texture_cache; + Vector<uint8_t> ubo_data; + uint64_t last_pass = 0; + uint32_t index = 0; + RID next_pass; + uint8_t priority; + virtual void set_render_priority(int p_priority); + virtual void set_next_pass(RID p_pass); + virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual ~MaterialData(); + }; + + RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) { + return static_cast<RendererSceneRenderForward *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader)); + } + + /* Framebuffer */ + + struct RenderBufferDataForward : public RenderBufferData { + //for rendering, may be MSAAd + + RID color; + RID depth; + RID specular; + RID normal_roughness_buffer; + RID giprobe_buffer; + + RID ambient_buffer; + RID reflection_buffer; + + RS::ViewportMSAA msaa; + RD::TextureSamples texture_samples; + + RID color_msaa; + RID depth_msaa; + RID specular_msaa; + RID normal_roughness_buffer_msaa; + RID roughness_buffer_msaa; + RID giprobe_buffer_msaa; + + RID depth_fb; + RID depth_normal_roughness_fb; + RID depth_normal_roughness_giprobe_fb; + RID color_fb; + RID color_specular_fb; + RID specular_only_fb; + int width, height; + + RID render_sdfgi_uniform_set; + void ensure_specular(); + void ensure_gi(); + void ensure_giprobe(); + void clear(); + virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa); + + ~RenderBufferDataForward(); + }; + + virtual RenderBufferData *_create_render_buffer_data(); + void _allocate_normal_roughness_texture(RenderBufferDataForward *rb); + + RID shadow_sampler; + RID render_base_uniform_set; + RID render_pass_uniform_set; + RID sdfgi_pass_uniform_set; + + uint64_t lightmap_texture_array_version = 0xFFFFFFFF; + + virtual void _base_uniforms_changed(); + void _render_buffers_clear_uniform_set(RenderBufferDataForward *rb); + virtual void _render_buffers_uniform_set_changed(RID p_render_buffers); + virtual RID _render_buffers_get_normal_texture(RID p_render_buffers); + virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers); + virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers); + + void _update_render_base_uniform_set(); + RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture); + RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps); + + struct LightmapData { + float normal_xform[12]; + }; + + struct LightmapCaptureData { + float sh[9 * 4]; + }; + + enum { + INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6, + INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7, + INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8, + INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9, + INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10, + INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11, + INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, + INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, + INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16, + INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7, + INSTANCE_DATA_FLAG_SKELETON = 1 << 19, + }; + + struct SceneState { + struct UBO { + float projection_matrix[16]; + float inv_projection_matrix[16]; + + float camera_matrix[16]; + float inv_camera_matrix[16]; + + float viewport_size[2]; + float screen_pixel_size[2]; + + float directional_penumbra_shadow_kernel[128]; //32 vec4s + float directional_soft_shadow_kernel[128]; + float penumbra_shadow_kernel[128]; + float soft_shadow_kernel[128]; + + uint32_t directional_penumbra_shadow_samples; + uint32_t directional_soft_shadow_samples; + uint32_t penumbra_shadow_samples; + uint32_t soft_shadow_samples; + + float ambient_light_color_energy[4]; + + float ambient_color_sky_mix; + uint32_t use_ambient_light; + uint32_t use_ambient_cubemap; + uint32_t use_reflection_cubemap; + + float radiance_inverse_xform[12]; + + float shadow_atlas_pixel_size[2]; + float directional_shadow_pixel_size[2]; + + uint32_t directional_light_count; + float dual_paraboloid_side; + float z_far; + float z_near; + + uint32_t ssao_enabled; + float ssao_light_affect; + float ssao_ao_affect; + uint32_t roughness_limiter_enabled; + + float roughness_limiter_amount; + float roughness_limiter_limit; + uint32_t roughness_limiter_pad[2]; + + float ao_color[4]; + + float sdf_to_bounds[16]; + + int32_t sdf_offset[3]; + uint32_t material_uv2_mode; + + int32_t sdf_size[3]; + uint32_t gi_upscale_for_msaa; + + uint32_t volumetric_fog_enabled; + float volumetric_fog_inv_length; + float volumetric_fog_detail_spread; + uint32_t volumetric_fog_pad; + + // Fog + uint32_t fog_enabled; + float fog_density; + float fog_height; + float fog_height_density; + + float fog_light_color[3]; + float fog_sun_scatter; + + float fog_aerial_perspective; + + float time; + float reflection_multiplier; + + uint32_t pancake_shadows; + }; + + UBO ubo; + + RID uniform_buffer; + + LightmapData lightmaps[MAX_LIGHTMAPS]; + RID lightmap_ids[MAX_LIGHTMAPS]; + bool lightmap_has_sh[MAX_LIGHTMAPS]; + uint32_t lightmaps_used = 0; + uint32_t max_lightmaps; + RID lightmap_buffer; + + LightmapCaptureData *lightmap_captures; + uint32_t max_lightmap_captures; + RID lightmap_capture_buffer; + + RID giprobe_ids[MAX_GI_PROBES]; + uint32_t giprobes_used = 0; + + bool used_screen_texture = false; + bool used_normal_texture = false; + bool used_depth_texture = false; + bool used_sss = false; + + } scene_state; + + static RendererSceneRenderForward *singleton; + uint64_t render_pass; + double time; + RID default_shader; + RID default_material; + RID overdraw_material_shader; + RID overdraw_material; + RID wireframe_material_shader; + RID wireframe_material; + RID default_shader_rd; + RID default_shader_sdfgi_rd; + + RID default_vec4_xform_buffer; + RID default_vec4_xform_uniform_set; + + enum PassMode { + PASS_MODE_COLOR, + PASS_MODE_COLOR_SPECULAR, + PASS_MODE_COLOR_TRANSPARENT, + PASS_MODE_SHADOW, + PASS_MODE_SHADOW_DP, + PASS_MODE_DEPTH, + PASS_MODE_DEPTH_NORMAL_ROUGHNESS, + PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE, + PASS_MODE_DEPTH_MATERIAL, + PASS_MODE_SDF, + }; + + void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false); + void _setup_giprobes(const PagedArray<RID> &p_giprobes); + void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform); + + struct GeometryInstanceSurfaceDataCache; + + struct RenderListParameters { + GeometryInstanceSurfaceDataCache **elements = nullptr; + int element_count = 0; + bool reverse_cull = false; + PassMode pass_mode = PASS_MODE_COLOR; + bool no_gi = false; + RID render_pass_uniform_set; + bool force_wireframe = false; + Vector2 uv_offset; + Plane lod_plane; + float lod_distance_multiplier = 0.0; + float screen_lod_threshold = 0.0; + RD::FramebufferFormatID framebuffer_format = 0; + RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) { + elements = p_elements; + element_count = p_element_count; + reverse_cull = p_reverse_cull; + pass_mode = p_pass_mode; + no_gi = p_no_gi; + render_pass_uniform_set = p_render_pass_uniform_set; + force_wireframe = p_force_wireframe; + uv_offset = p_uv_offset; + lod_plane = p_lod_plane; + lod_distance_multiplier = p_lod_distance_multiplier; + screen_lod_threshold = p_screen_lod_threshold; + } + }; + + template <PassMode p_pass_mode> + _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); + + 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); + + LocalVector<RD::DrawListID> thread_draw_lists; + void _render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params); + 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>()); + + uint32_t render_list_thread_threshold = 500; + + void _fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false, bool p_using_opaque_gi = false); + + Map<Size2i, RID> sdfgi_framebuffer_size_cache; + + struct GeometryInstanceData; + struct GeometryInstanceForward; + + struct GeometryInstanceLightmapSH { + Color sh[9]; + }; + + // Cached data for drawing surfaces + struct GeometryInstanceSurfaceDataCache { + enum { + FLAG_PASS_DEPTH = 1, + FLAG_PASS_OPAQUE = 2, + FLAG_PASS_ALPHA = 4, + FLAG_PASS_SHADOW = 8, + FLAG_USES_SHARED_SHADOW_MATERIAL = 128, + FLAG_USES_SUBSURFACE_SCATTERING = 2048, + FLAG_USES_SCREEN_TEXTURE = 4096, + FLAG_USES_DEPTH_TEXTURE = 8192, + FLAG_USES_NORMAL_TEXTURE = 16384, + FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768, + }; + + union { + struct { + uint32_t geometry_id; + uint32_t material_id; + uint32_t shader_id; + uint32_t surface_type : 4; + uint32_t uses_forward_gi : 1; //set during addition + uint32_t uses_lightmap : 1; //set during addition + uint32_t depth_layer : 4; //set during addition + uint32_t priority : 8; + }; + struct { + uint64_t sort_key1; + uint64_t sort_key2; + }; + } sort; + + RS::PrimitiveType primitive = RS::PRIMITIVE_MAX; + uint32_t flags = 0; + uint32_t surface_index = 0; + + void *surface = nullptr; + RID material_uniform_set; + ShaderData *shader = nullptr; + + void *surface_shadow = nullptr; + RID material_uniform_set_shadow; + ShaderData *shader_shadow = nullptr; + + GeometryInstanceSurfaceDataCache *next = nullptr; + GeometryInstanceForward *owner = nullptr; + }; + + struct GeometryInstanceForward : public GeometryInstance { + //used during rendering + bool mirror = false; + bool non_uniform_scale = false; + float lod_bias = 0.0; + float lod_model_scale = 1.0; + AABB transformed_aabb; //needed for LOD + float depth = 0; + struct PushConstant { + float transform[16]; + uint32_t flags; + uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables + uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index) + uint32_t layer_mask; + float lightmap_uv_scale[4]; + } push_constant; + RID transforms_uniform_set; + uint32_t instance_count = 0; + RID mesh_instance; + bool can_sdfgi = false; + //used during setup + uint32_t base_flags = 0; + RID gi_probes[MAX_GI_PROBES_PER_INSTANCE]; + RID lightmap_instance; + GeometryInstanceLightmapSH *lightmap_sh = nullptr; + GeometryInstanceSurfaceDataCache *surface_caches = nullptr; + SelfList<GeometryInstanceForward> dirty_list_element; + + struct Data { + //data used less often goes into regular heap + RID base; + RS::InstanceType base_type; + + RID skeleton; + + uint32_t layer_mask = 1; + + Vector<RID> surface_materials; + RID material_override; + Transform transform; + AABB aabb; + int32_t shader_parameters_offset = -1; + + bool use_dynamic_gi = false; + bool use_baked_light = false; + bool cast_double_sided_shaodows = false; + bool mirror = false; + Rect2 lightmap_uv_scale; + uint32_t lightmap_slice_index = 0; + bool dirty_dependencies = false; + + RendererStorage::DependencyTracker dependency_tracker; + }; + + Data *data = nullptr; + + GeometryInstanceForward() : + dirty_list_element(this) {} + }; + + static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker); + static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker); + + SelfList<GeometryInstanceForward>::List geometry_instance_dirty_list; + + PagedAllocator<GeometryInstanceForward> geometry_instance_alloc; + PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc; + PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh; + + void _geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); + void _geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); + void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); + void _geometry_instance_update(GeometryInstance *p_geometry_instance); + void _update_dirty_geometry_instances(); + + bool low_end = false; + + /* Render List */ + + struct RenderList { + int max_elements; + + GeometryInstanceSurfaceDataCache **elements = nullptr; + + int element_count; + int alpha_element_count; + + void clear() { + element_count = 0; + alpha_element_count = 0; + } + + //should eventually be replaced by radix + + struct SortByKey { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { + 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); + } + }; + + void sort_by_key(bool p_alpha) { + SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter; + if (p_alpha) { + sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); + } else { + sorter.sort(elements, element_count); + } + } + + struct SortByDepth { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { + return (A->owner->depth < B->owner->depth); + } + }; + + void sort_by_depth(bool p_alpha) { //used for shadows + + SortArray<GeometryInstanceSurfaceDataCache *, SortByDepth> sorter; + if (p_alpha) { + sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); + } else { + sorter.sort(elements, element_count); + } + } + + struct SortByReverseDepthAndPriority { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { + return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority); + } + }; + + void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha + + SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter; + if (p_alpha) { + sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); + } else { + sorter.sort(elements, element_count); + } + } + + _FORCE_INLINE_ void add_element(GeometryInstanceSurfaceDataCache *p_element) { + if (element_count + alpha_element_count >= max_elements) { + return; + } + elements[element_count] = p_element; + element_count++; + } + + _FORCE_INLINE_ void add_alpha_element(GeometryInstanceSurfaceDataCache *p_element) { + if (element_count + alpha_element_count >= max_elements) { + return; + } + int idx = max_elements - alpha_element_count - 1; + elements[idx] = p_element; + alpha_element_count++; + } + + void init() { + element_count = 0; + alpha_element_count = 0; + elements = memnew_arr(GeometryInstanceSurfaceDataCache *, max_elements); + } + + RenderList() { + max_elements = 0; + } + + ~RenderList() { + memdelete_arr(elements); + } + }; + + RenderList render_list; + +protected: + virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold); + virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &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_lod_threshold = 0.0); + virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region); + virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region); + virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture); + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances); + +public: + virtual GeometryInstance *geometry_instance_create(RID p_base); + virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton); + virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override); + virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials); + virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance); + virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb); + virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask); + virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias); + virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable); + virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable); + virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index); + virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9); + virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset); + virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable); + + virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance); + virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance); + + virtual void geometry_instance_free(GeometryInstance *p_geometry_instance); + + virtual uint32_t geometry_instance_get_pair_mask(); + virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count); + virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count); + virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count); + virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count); + + virtual void set_time(double p_time, double p_step); + + virtual bool free(RID p_rid); + + RendererSceneRenderForward(RendererStorageRD *p_storage); + ~RendererSceneRenderForward(); +}; +#endif // RASTERIZER_SCENE_HIGHEND_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 12fcc6fbb9..a655edcfa7 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_scene_rd.cpp */ +/* renderer_scene_render_rd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rasterizer_scene_rd.h" +#include "renderer_scene_render_rd.h" #include "core/config/project_settings.h" #include "core/os/os.h" -#include "rasterizer_rd.h" -#include "servers/rendering/rendering_server_raster.h" +#include "renderer_compositor_rd.h" +#include "servers/rendering/rendering_server_default.h" -uint64_t RasterizerSceneRD::auto_exposure_counter = 2; +uint64_t RendererSceneRenderRD::auto_exposure_counter = 2; void get_vogel_disk(float *r_kernel, int p_sample_count) { const float golden_angle = 2.4; @@ -49,7 +49,7 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) { } } -void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) { +void RendererSceneRenderRD::_clear_reflection_data(ReflectionData &rd) { rd.layers.clear(); rd.radiance_base_cubemap = RID(); if (rd.downsampled_radiance_cubemap.is_valid()) { @@ -60,7 +60,7 @@ void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) { rd.coefficient_buffer = RID(); } -void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality) { +void RendererSceneRenderRD::_update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality) { //recreate radiance and all data int mipmaps = p_mipmaps; @@ -129,7 +129,7 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = 64; // Always 64x64 tf.height = 64; - tf.type = RD::TEXTURE_TYPE_CUBE; + tf.texture_type = RD::TEXTURE_TYPE_CUBE; tf.array_layers = 6; tf.mipmaps = 7; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; @@ -151,7 +151,7 @@ void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, } } -void RasterizerSceneRD::_create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays) { +void RendererSceneRenderRD::_create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays) { storage->get_effects()->cubemap_downsample(rd.radiance_base_cubemap, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size); for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) { @@ -172,7 +172,7 @@ void RasterizerSceneRD::_create_reflection_fast_filter(ReflectionData &rd, bool storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, views, p_use_arrays); } -void RasterizerSceneRD::_create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer) { +void RendererSceneRenderRD::_create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer) { if (p_use_arrays) { //render directly to the layers storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, rd.layers[p_base_layer].views[0], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers.size() - 1.0), rd.layers[p_base_layer].mipmaps[0].size.x); @@ -181,7 +181,7 @@ void RasterizerSceneRD::_create_reflection_importance_sample(ReflectionData &rd, } } -void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd, int p_start, int p_end) { +void RendererSceneRenderRD::_update_reflection_mipmaps(ReflectionData &rd, int p_start, int p_end) { for (int i = p_start; i < p_end; i++) { for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) { for (int k = 0; k < 6; k++) { @@ -194,7 +194,7 @@ void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd, int p_sta } } -void RasterizerSceneRD::_sdfgi_erase(RenderBuffers *rb) { +void RendererSceneRenderRD::_sdfgi_erase(RenderBuffers *rb) { for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { const SDFGI::Cascade &c = rb->sdfgi->cascades[i]; RD::get_singleton()->free(c.light_data); @@ -236,9 +236,9 @@ void RasterizerSceneRD::_sdfgi_erase(RenderBuffers *rb) { rb->sdfgi = nullptr; } -const Vector3i RasterizerSceneRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF); +const Vector3i RendererSceneRenderRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF); -void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) { +void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) { Environment *env = environment_owner.getornull(p_environment); RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); bool needs_sdfgi = env && env->sdfgi_enabled; @@ -284,7 +284,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co tf_sdf.width = sdfgi->cascade_size; // Always 64x64 tf_sdf.height = sdfgi->cascade_size; tf_sdf.depth = sdfgi->cascade_size; - tf_sdf.type = RD::TEXTURE_TYPE_3D; + tf_sdf.texture_type = RD::TEXTURE_TYPE_3D; tf_sdf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; { @@ -341,7 +341,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co tf_probes.width = sdfgi->probe_axis_count * sdfgi->probe_axis_count; tf_probes.height = sdfgi->probe_axis_count * SDFGI::SH_SIZE; tf_probes.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - tf_probes.type = RD::TEXTURE_TYPE_2D_ARRAY; + tf_probes.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; sdfgi->history_size = requested_history_size; @@ -351,7 +351,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co RD::TextureFormat tf_probe_average = tf_probes; tf_probe_average.format = RD::DATA_FORMAT_R32G32B32A32_SINT; //signed integer because SH are signed - tf_probe_average.type = RD::TEXTURE_TYPE_2D; + tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D; sdfgi->lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); sdfgi->lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); @@ -378,7 +378,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co tf_ambient.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; //pack well with RGBE tf_ambient.width = sdfgi->probe_axis_count * sdfgi->probe_axis_count; tf_ambient.height = sdfgi->probe_axis_count; - tf_ambient.type = RD::TEXTURE_TYPE_2D_ARRAY; + tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; //lightprobe texture is an octahedral texture sdfgi->ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView()); } @@ -443,21 +443,21 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(sdfgi->render_sdf[(passes & 1) ? 1 : 0]); //if passes are even, we read from buffer 0, else we read from buffer 1 uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(sdfgi->render_albedo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; for (int j = 0; j < 8; j++) { u.ids.push_back(sdfgi->render_occlusion[j]); @@ -466,21 +466,21 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 4; u.ids.push_back(sdfgi->render_emission); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; u.ids.push_back(sdfgi->render_emission_aniso); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 6; u.ids.push_back(sdfgi->render_geom_facing); uniforms.push_back(u); @@ -488,28 +488,28 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 7; u.ids.push_back(cascade.sdf_tex); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; u.ids.push_back(sdfgi->occlusion_data); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 10; u.ids.push_back(cascade.solid_cell_dispatch_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 11; u.ids.push_back(cascade.solid_cell_buffer); uniforms.push_back(u); @@ -522,42 +522,42 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(sdfgi->render_albedo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(sdfgi->render_geom_facing); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; u.ids.push_back(sdfgi->render_emission); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 4; u.ids.push_back(sdfgi->render_emission_aniso); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 5; u.ids.push_back(cascade.solid_cell_dispatch_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 6; u.ids.push_back(cascade.solid_cell_buffer); uniforms.push_back(u); @@ -569,7 +569,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; for (int j = 0; j < 8; j++) { u.ids.push_back(sdfgi->render_occlusion[j]); @@ -578,7 +578,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(sdfgi->occlusion_data); uniforms.push_back(u); @@ -596,12 +596,12 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[j].sdf_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -609,63 +609,63 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; u.binding = 2; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; u.binding = 3; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(cascade.solid_cell_dispatch_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 4; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(cascade.solid_cell_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 5; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.ids.push_back(cascade.light_data); uniforms.push_back(u); } { RD::Uniform u; u.binding = 6; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.ids.push_back(cascade.light_aniso_0_tex); uniforms.push_back(u); } { RD::Uniform u; u.binding = 7; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.ids.push_back(cascade.light_aniso_1_tex); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.ids.push_back(rb->sdfgi->cascades_ubo); uniforms.push_back(u); } { RD::Uniform u; u.binding = 9; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(cascade.lights_buffer); uniforms.push_back(u); } { RD::Uniform u; u.binding = 10; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.push_back(rb->sdfgi->lightprobe_texture); uniforms.push_back(u); } @@ -678,14 +678,14 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(sdfgi->render_albedo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(sdfgi->render_sdf[0]); uniforms.push_back(u); @@ -698,14 +698,14 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(sdfgi->render_albedo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(sdfgi->render_sdf_half[0]); uniforms.push_back(u); @@ -719,14 +719,14 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(sdfgi->render_sdf[0]); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(sdfgi->render_sdf[1]); uniforms.push_back(u); @@ -741,14 +741,14 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(sdfgi->render_sdf_half[0]); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(sdfgi->render_sdf_half[1]); uniforms.push_back(u); @@ -764,21 +764,21 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(sdfgi->render_albedo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(sdfgi->render_sdf_half[(passes & 1) ? 0 : 1]); //reverse pass order because half size uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; u.ids.push_back(sdfgi->render_sdf[(passes & 1) ? 0 : 1]); //reverse pass order because it needs an extra JFA pass uniforms.push_back(u); @@ -793,14 +793,14 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(sdfgi->render_albedo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; for (int i = 0; i < 8; i++) { u.ids.push_back(sdfgi->render_occlusion[i]); @@ -809,7 +809,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; u.ids.push_back(sdfgi->render_geom_facing); uniforms.push_back(u); @@ -826,12 +826,12 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < sdfgi->cascades.size()) { u.ids.push_back(sdfgi->cascades[j].sdf_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -839,12 +839,12 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < sdfgi->cascades.size()) { u.ids.push_back(sdfgi->cascades[j].light_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -852,12 +852,12 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; u.binding = 3; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < sdfgi->cascades.size()) { u.ids.push_back(sdfgi->cascades[j].light_aniso_0_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -865,19 +865,19 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; u.binding = 4; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (j < sdfgi->cascades.size()) { u.ids.push_back(sdfgi->cascades[j].light_aniso_1_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 6; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); @@ -885,14 +885,14 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 7; u.ids.push_back(sdfgi->cascades_ubo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; u.ids.push_back(sdfgi->lightprobe_data); uniforms.push_back(u); @@ -900,14 +900,14 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; u.ids.push_back(sdfgi->cascades[i].lightprobe_history_tex); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; u.ids.push_back(sdfgi->cascades[i].lightprobe_average_tex); uniforms.push_back(u); @@ -915,21 +915,21 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 11; u.ids.push_back(sdfgi->lightprobe_history_scroll); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 12; u.ids.push_back(sdfgi->lightprobe_average_scroll); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 13; RID parent_average; if (i < sdfgi->cascades.size() - 1) { @@ -942,7 +942,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 14; u.ids.push_back(sdfgi->ambient_texture); uniforms.push_back(u); @@ -1021,7 +1021,7 @@ void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, co } } -int RasterizerSceneRD::sdfgi_get_pending_region_count(RID p_render_buffers) const { +int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers) const { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(rb == nullptr, 0); @@ -1048,7 +1048,7 @@ int RasterizerSceneRD::sdfgi_get_pending_region_count(RID p_render_buffers) cons return dirty_count; } -int RasterizerSceneRD::_sdfgi_get_pending_region_data(RID p_render_buffers, int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const { +int RendererSceneRenderRD::_sdfgi_get_pending_region_data(RID p_render_buffers, int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(rb == nullptr, -1); ERR_FAIL_COND_V(rb->sdfgi == nullptr, -1); @@ -1108,7 +1108,7 @@ int RasterizerSceneRD::_sdfgi_get_pending_region_data(RID p_render_buffers, int return -1; } -AABB RasterizerSceneRD::sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const { +AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const { AABB bounds; Vector3i from; Vector3i size; @@ -1118,7 +1118,7 @@ AABB RasterizerSceneRD::sdfgi_get_pending_region_bounds(RID p_render_buffers, in return bounds; } -uint32_t RasterizerSceneRD::sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const { +uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const { AABB bounds; Vector3i from; Vector3i size; @@ -1126,7 +1126,7 @@ uint32_t RasterizerSceneRD::sdfgi_get_pending_region_cascade(RID p_render_buffer return _sdfgi_get_pending_region_data(p_render_buffers, p_region, from, size, bounds); } -void RasterizerSceneRD::_sdfgi_update_cascades(RID p_render_buffers) { +void RendererSceneRenderRD::_sdfgi_update_cascades(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(rb == nullptr); if (rb->sdfgi == nullptr) { @@ -1153,7 +1153,7 @@ void RasterizerSceneRD::_sdfgi_update_cascades(RID p_render_buffers) { RD::get_singleton()->buffer_update(rb->sdfgi->cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, true); } -void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) { +void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_environment, const Vector<RID> &p_directional_lights, const RID *p_positional_light_instances, uint32_t p_positional_light_count) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(rb == nullptr); if (rb->sdfgi == nullptr) { @@ -1179,13 +1179,18 @@ void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environm SDGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS]; uint32_t idx = 0; - for (uint32_t j = 0; j < p_directional_light_count; j++) { + for (uint32_t j = 0; j < (uint32_t)p_directional_lights.size(); j++) { if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { break; } - LightInstance *li = light_instance_owner.getornull(p_directional_light_instances[j]); + LightInstance *li = light_instance_owner.getornull(p_directional_lights[j]); ERR_CONTINUE(!li); + + if (storage->light_directional_is_sky_only(li->light)) { + continue; + } + Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); dir.y *= rb->sdfgi->y_mult; dir.normalize(); @@ -1333,7 +1338,7 @@ void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environm { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; u.ids.push_back(sky->radiance); uniforms.push_back(u); @@ -1341,7 +1346,7 @@ void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environm { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 1; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); @@ -1397,7 +1402,7 @@ void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environm RENDER_TIMESTAMP("<SDFGI Update Probes"); } -void RasterizerSceneRD::_setup_giprobes(RID p_render_buffers, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, uint32_t &r_gi_probes_used) { +void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used) { r_gi_probes_used = 0; RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(rb == nullptr); @@ -1412,8 +1417,8 @@ void RasterizerSceneRD::_setup_giprobes(RID p_render_buffers, const Transform &p for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) { RID texture; - if (i < p_gi_probe_cull_count) { - GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_gi_probe_cull_result[i]); + if (i < (int)p_gi_probes.size()) { + GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_gi_probes[i]); if (gipi) { texture = gipi->texture; @@ -1460,7 +1465,7 @@ void RasterizerSceneRD::_setup_giprobes(RID p_render_buffers, const Transform &p } if (texture == RID()) { - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); } if (texture != rb->giprobe_textures[i]) { @@ -1484,12 +1489,12 @@ void RasterizerSceneRD::_setup_giprobes(RID p_render_buffers, const Transform &p } } - if (p_gi_probe_cull_count > 0) { - RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GI::GIProbeData) * MIN(RenderBuffers::MAX_GIPROBES, p_gi_probe_cull_count), gi_probe_data, true); + if (p_gi_probes.size() > 0) { + RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GI::GIProbeData) * MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size()), gi_probe_data, true); } } -void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) { +void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes) { RENDER_TIMESTAMP("Render GI"); RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); @@ -1507,7 +1512,7 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]); push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; - push_constant.max_giprobes = MIN(RenderBuffers::MAX_GIPROBES, p_gi_probe_cull_count); + push_constant.max_giprobes = MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size()); push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH; push_constant.use_sdfgi = rb->sdfgi != nullptr; @@ -1609,12 +1614,12 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness { RD::Uniform u; u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[j].sdf_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1622,12 +1627,12 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness { RD::Uniform u; u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[j].light_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1635,12 +1640,12 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness { RD::Uniform u; u.binding = 3; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_0_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1648,37 +1653,37 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness { RD::Uniform u; u.binding = 4; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_1_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 5; if (rb->sdfgi) { u.ids.push_back(rb->sdfgi->occlusion_texture); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 6; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 7; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); @@ -1686,7 +1691,7 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; u.ids.push_back(p_ambient_buffer); uniforms.push_back(u); @@ -1694,7 +1699,7 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; u.ids.push_back(p_reflection_buffer); uniforms.push_back(u); @@ -1702,54 +1707,54 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 11; if (rb->sdfgi) { u.ids.push_back(rb->sdfgi->lightprobe_texture); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 12; u.ids.push_back(rb->depth_texture); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 13; u.ids.push_back(p_normal_roughness_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 14; - RID buffer = p_gi_probe_buffer.is_valid() ? p_gi_probe_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID buffer = p_gi_probe_buffer.is_valid() ? p_gi_probe_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 15; u.ids.push_back(gi.sdfgi_ubo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 16; u.ids.push_back(rb->giprobe_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 17; for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) { u.ids.push_back(rb->giprobe_textures[i]); @@ -1768,11 +1773,11 @@ void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness RD::get_singleton()->compute_list_end(); } -RID RasterizerSceneRD::sky_create() { +RID RendererSceneRenderRD::sky_create() { return sky_owner.make_rid(Sky()); } -void RasterizerSceneRD::_sky_invalidate(Sky *p_sky) { +void RendererSceneRenderRD::_sky_invalidate(Sky *p_sky) { if (!p_sky->dirty) { p_sky->dirty = true; p_sky->dirty_list = dirty_sky_list; @@ -1780,7 +1785,7 @@ void RasterizerSceneRD::_sky_invalidate(Sky *p_sky) { } } -void RasterizerSceneRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { +void RendererSceneRenderRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { Sky *sky = sky_owner.getornull(p_sky); ERR_FAIL_COND(!sky); ERR_FAIL_COND(p_radiance_size < 32 || p_radiance_size > 2048); @@ -1802,7 +1807,7 @@ void RasterizerSceneRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { _clear_reflection_data(sky->reflection); } -void RasterizerSceneRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { +void RendererSceneRenderRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { Sky *sky = sky_owner.getornull(p_sky); ERR_FAIL_COND(!sky); @@ -1825,14 +1830,14 @@ void RasterizerSceneRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { _clear_reflection_data(sky->reflection); } -void RasterizerSceneRD::sky_set_material(RID p_sky, RID p_material) { +void RendererSceneRenderRD::sky_set_material(RID p_sky, RID p_material) { Sky *sky = sky_owner.getornull(p_sky); ERR_FAIL_COND(!sky); sky->material = p_material; _sky_invalidate(sky); } -Ref<Image> RasterizerSceneRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { +Ref<Image> RendererSceneRenderRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { Sky *sky = sky_owner.getornull(p_sky); ERR_FAIL_COND_V(!sky, Ref<Image>()); @@ -1868,7 +1873,7 @@ Ref<Image> RasterizerSceneRD::sky_bake_panorama(RID p_sky, float p_energy, bool return Ref<Image>(); } -void RasterizerSceneRD::_update_dirty_skys() { +void RendererSceneRenderRD::_update_dirty_skys() { Sky *sky = dirty_sky_list; while (sky) { @@ -1892,7 +1897,7 @@ void RasterizerSceneRD::_update_dirty_skys() { RD::TextureFormat tf; tf.array_layers = layers * 6; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY; + tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; tf.mipmaps = mipmaps; tf.width = w; tf.height = h; @@ -1907,7 +1912,7 @@ void RasterizerSceneRD::_update_dirty_skys() { RD::TextureFormat tf; tf.array_layers = 6; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.type = RD::TEXTURE_TYPE_CUBE; + tf.texture_type = RD::TEXTURE_TYPE_CUBE; tf.mipmaps = MIN(mipmaps, layers); tf.width = w; tf.height = h; @@ -1927,7 +1932,7 @@ void RasterizerSceneRD::_update_dirty_skys() { tformat.width = sky->screen_size.x / 2; tformat.height = sky->screen_size.y / 2; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; + tformat.texture_type = RD::TEXTURE_TYPE_2D; sky->half_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); Vector<RID> texs; @@ -1942,7 +1947,7 @@ void RasterizerSceneRD::_update_dirty_skys() { tformat.width = sky->screen_size.x / 4; tformat.height = sky->screen_size.y / 4; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; + tformat.texture_type = RD::TEXTURE_TYPE_2D; sky->quarter_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); Vector<RID> texs; @@ -1972,14 +1977,14 @@ void RasterizerSceneRD::_update_dirty_skys() { dirty_sky_list = nullptr; } -RID RasterizerSceneRD::sky_get_radiance_texture_rd(RID p_sky) const { +RID RendererSceneRenderRD::sky_get_radiance_texture_rd(RID p_sky) const { Sky *sky = sky_owner.getornull(p_sky); ERR_FAIL_COND_V(!sky, RID()); return sky->radiance; } -RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const { +RID RendererSceneRenderRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const { Sky *sky = sky_owner.getornull(p_sky); ERR_FAIL_COND_V(!sky, RID()); @@ -1989,7 +1994,7 @@ RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; u.ids.push_back(sky->radiance); uniforms.push_back(u); @@ -2002,25 +2007,25 @@ RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, return sky->uniform_set; } -RID RasterizerSceneRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version) { +RID RendererSceneRenderRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version) { if (p_sky->texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(p_sky->texture_uniform_sets[p_version])) { return p_sky->texture_uniform_sets[p_version]; } Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; if (p_sky->radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { u.ids.push_back(p_sky->radiance); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; // half res if (p_sky->half_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { @@ -2030,16 +2035,16 @@ RID RasterizerSceneRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_vers } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; // quarter res if (p_sky->quarter_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { @@ -2049,9 +2054,9 @@ RID RasterizerSceneRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_vers } } else { if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } uniforms.push_back(u); @@ -2061,14 +2066,14 @@ RID RasterizerSceneRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_vers return p_sky->texture_uniform_sets[p_version]; } -RID RasterizerSceneRD::sky_get_material(RID p_sky) const { +RID RendererSceneRenderRD::sky_get_material(RID p_sky) const { Sky *sky = sky_owner.getornull(p_sky); ERR_FAIL_COND_V(!sky, RID()); return sky->material; } -void RasterizerSceneRD::_draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) { +void RendererSceneRenderRD::_draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) { ERR_FAIL_COND(!is_environment(p_environment)); SkyMaterialData *material = nullptr; @@ -2084,7 +2089,7 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue_color, bool p_can_continue sky_material = sky_get_material(environment_get_sky(p_environment)); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2092,13 +2097,13 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue_color, bool p_can_continue if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); } ERR_FAIL_COND(!material); @@ -2129,7 +2134,7 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue_color, bool p_can_continue sky_transform = p_transform.basis * sky_transform; if (shader_data->uses_quarter_res) { - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES]; + PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES]; RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_QUARTER_RES); @@ -2142,7 +2147,7 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue_color, bool p_can_continue } if (shader_data->uses_half_res) { - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES]; + PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES]; RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_HALF_RES); @@ -2154,7 +2159,7 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue_color, bool p_can_continue RD::get_singleton()->draw_list_end(); } - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND]; + PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND]; RID texture_uniform_set; if (sky) { @@ -2168,7 +2173,7 @@ void RasterizerSceneRD::_draw_sky(bool p_can_continue_color, bool p_can_continue RD::get_singleton()->draw_list_end(); } -void RasterizerSceneRD::_setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size) { +void RendererSceneRenderRD::_setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size) { ERR_FAIL_COND(!is_environment(p_environment)); SkyMaterialData *material = nullptr; @@ -2186,7 +2191,7 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, RID p_render_buffers, cons sky_material = sky_get_material(environment_get_sky(p_environment)); if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2194,7 +2199,7 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, RID p_render_buffers, cons if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); } ERR_FAIL_COND(!material); @@ -2237,7 +2242,7 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, RID p_render_buffers, cons if (shader_data->uses_time && time - sky->prev_time > 0.00001) { sky->prev_time = time; sky->reflection.dirty = true; - RenderingServerRaster::redraw_request(); + RenderingServerDefault::redraw_request(); } if (material != sky->prev_material) { @@ -2285,7 +2290,7 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, RID p_render_buffers, cons if (light_data_dirty) { RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights, true); - RasterizerSceneRD::SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights; + RendererSceneRenderRD::SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights; sky_scene_state.last_frame_directional_lights = sky_scene_state.directional_lights; sky_scene_state.directional_lights = temp; sky_scene_state.last_frame_directional_light_count = sky_scene_state.ubo.directional_light_count; @@ -2338,7 +2343,7 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, RID p_render_buffers, cons RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo, true); } -void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) { +void RendererSceneRenderRD::_update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) { ERR_FAIL_COND(!is_environment(p_environment)); Sky *sky = sky_owner.getornull(environment_get_sky(p_environment)); @@ -2349,7 +2354,7 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro SkyMaterialData *material = nullptr; if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -2357,7 +2362,7 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro if (!material) { sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + material = (SkyMaterialData *)storage->material_get_data(sky_material, RendererStorageRD::SHADER_TYPE_SKY); } ERR_FAIL_COND(!material); @@ -2418,7 +2423,7 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro cm = correction * cm; if (shader_data->uses_quarter_res) { - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES]; + PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES]; Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); @@ -2436,7 +2441,7 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro } if (shader_data->uses_half_res) { - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES]; + PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES]; Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); @@ -2454,7 +2459,7 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro } RD::DrawListID cubemap_draw_list; - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP]; + PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP]; for (int i = 0; i < 6; i++) { Transform local_view; @@ -2505,7 +2510,7 @@ void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_pro /* SKY SHADER */ -void RasterizerSceneRD::SkyShaderData::set_code(const String &p_code) { +void RendererSceneRenderRD::SkyShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -2554,7 +2559,7 @@ void RasterizerSceneRD::SkyShaderData::set_code(const String &p_code) { actions.uniforms = &uniforms; - RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; + RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; Error err = scene_singleton->sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code); @@ -2599,7 +2604,7 @@ void RasterizerSceneRD::SkyShaderData::set_code(const String &p_code) { valid = true; } -void RasterizerSceneRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererSceneRenderRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { if (!p_texture.is_valid()) { default_texture_params.erase(p_name); } else { @@ -2607,7 +2612,7 @@ void RasterizerSceneRD::SkyShaderData::set_default_texture_param(const StringNam } } -void RasterizerSceneRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void RendererSceneRenderRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { Map<int, StringName> order; for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { @@ -2629,13 +2634,13 @@ void RasterizerSceneRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_para } } -void RasterizerSceneRD::SkyShaderData::get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const { +void RendererSceneRenderRD::SkyShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RasterizerStorage::InstanceShaderParam p; + RendererStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E->get()); p.info.name = E->key(); //supply name p.index = E->get().instance_index; @@ -2644,7 +2649,7 @@ void RasterizerSceneRD::SkyShaderData::get_instance_param_list(List<RasterizerSt } } -bool RasterizerSceneRD::SkyShaderData::is_param_texture(const StringName &p_param) const { +bool RendererSceneRenderRD::SkyShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -2652,15 +2657,15 @@ bool RasterizerSceneRD::SkyShaderData::is_param_texture(const StringName &p_para return uniforms[p_param].texture_order >= 0; } -bool RasterizerSceneRD::SkyShaderData::is_animated() const { +bool RendererSceneRenderRD::SkyShaderData::is_animated() const { return false; } -bool RasterizerSceneRD::SkyShaderData::casts_shadows() const { +bool RendererSceneRenderRD::SkyShaderData::casts_shadows() const { return false; } -Variant RasterizerSceneRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant RendererSceneRenderRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -2669,12 +2674,18 @@ Variant RasterizerSceneRD::SkyShaderData::get_default_parameter(const StringName return Variant(); } -RasterizerSceneRD::SkyShaderData::SkyShaderData() { +RS::ShaderNativeSourceCode RendererSceneRenderRD::SkyShaderData::get_native_source_code() const { + RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + + return scene_singleton->sky_shader.shader.version_get_native_source_code(version); +} + +RendererSceneRenderRD::SkyShaderData::SkyShaderData() { valid = false; } -RasterizerSceneRD::SkyShaderData::~SkyShaderData() { - RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; +RendererSceneRenderRD::SkyShaderData::~SkyShaderData() { + RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; ERR_FAIL_COND(!scene_singleton); //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { @@ -2682,13 +2693,13 @@ RasterizerSceneRD::SkyShaderData::~SkyShaderData() { } } -RasterizerStorageRD::ShaderData *RasterizerSceneRD::_create_sky_shader_func() { +RendererStorageRD::ShaderData *RendererSceneRenderRD::_create_sky_shader_func() { SkyShaderData *shader_data = memnew(SkyShaderData); return shader_data; } -void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; +void RendererSceneRenderRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; uniform_set_updated = true; @@ -2750,7 +2761,7 @@ void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName, { if (shader_data->ubo_size) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 0; u.ids.push_back(uniform_buffer); uniforms.push_back(u); @@ -2759,7 +2770,7 @@ void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName, const RID *textures = texture_cache.ptrw(); for (uint32_t i = 0; i < tex_uniform_count; i++) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1 + i; u.ids.push_back(textures[i]); uniforms.push_back(u); @@ -2769,7 +2780,7 @@ void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map<StringName, uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); } -RasterizerSceneRD::SkyMaterialData::~SkyMaterialData() { +RendererSceneRenderRD::SkyMaterialData::~SkyMaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } @@ -2779,7 +2790,7 @@ RasterizerSceneRD::SkyMaterialData::~SkyMaterialData() { } } -RasterizerStorageRD::MaterialData *RasterizerSceneRD::_create_sky_material_func(SkyShaderData *p_shader) { +RendererStorageRD::MaterialData *RendererSceneRenderRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); material_data->shader_data = p_shader; material_data->last_frame = false; @@ -2787,53 +2798,53 @@ RasterizerStorageRD::MaterialData *RasterizerSceneRD::_create_sky_material_func( return material_data; } -RID RasterizerSceneRD::environment_create() { +RID RendererSceneRenderRD::environment_create() { return environment_owner.make_rid(Environment()); } -void RasterizerSceneRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { +void RendererSceneRenderRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->background = p_bg; } -void RasterizerSceneRD::environment_set_sky(RID p_env, RID p_sky) { +void RendererSceneRenderRD::environment_set_sky(RID p_env, RID p_sky) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->sky = p_sky; } -void RasterizerSceneRD::environment_set_sky_custom_fov(RID p_env, float p_scale) { +void RendererSceneRenderRD::environment_set_sky_custom_fov(RID p_env, float p_scale) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->sky_custom_fov = p_scale; } -void RasterizerSceneRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { +void RendererSceneRenderRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->sky_orientation = p_orientation; } -void RasterizerSceneRD::environment_set_bg_color(RID p_env, const Color &p_color) { +void RendererSceneRenderRD::environment_set_bg_color(RID p_env, const Color &p_color) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->bg_color = p_color; } -void RasterizerSceneRD::environment_set_bg_energy(RID p_env, float p_energy) { +void RendererSceneRenderRD::environment_set_bg_energy(RID p_env, float p_energy) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->bg_energy = p_energy; } -void RasterizerSceneRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { +void RendererSceneRenderRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->canvas_max_layer = p_max_layer; } -void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) { +void RendererSceneRenderRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->ambient_light = p_color; @@ -2844,85 +2855,85 @@ void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_ env->ao_color = p_ao_color; } -RS::EnvironmentBG RasterizerSceneRD::environment_get_background(RID p_env) const { +RS::EnvironmentBG RendererSceneRenderRD::environment_get_background(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX); return env->background; } -RID RasterizerSceneRD::environment_get_sky(RID p_env) const { +RID RendererSceneRenderRD::environment_get_sky(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, RID()); return env->sky; } -float RasterizerSceneRD::environment_get_sky_custom_fov(RID p_env) const { +float RendererSceneRenderRD::environment_get_sky_custom_fov(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->sky_custom_fov; } -Basis RasterizerSceneRD::environment_get_sky_orientation(RID p_env) const { +Basis RendererSceneRenderRD::environment_get_sky_orientation(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, Basis()); return env->sky_orientation; } -Color RasterizerSceneRD::environment_get_bg_color(RID p_env) const { +Color RendererSceneRenderRD::environment_get_bg_color(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, Color()); return env->bg_color; } -float RasterizerSceneRD::environment_get_bg_energy(RID p_env) const { +float RendererSceneRenderRD::environment_get_bg_energy(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->bg_energy; } -int RasterizerSceneRD::environment_get_canvas_max_layer(RID p_env) const { +int RendererSceneRenderRD::environment_get_canvas_max_layer(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->canvas_max_layer; } -Color RasterizerSceneRD::environment_get_ambient_light_color(RID p_env) const { +Color RendererSceneRenderRD::environment_get_ambient_light_color(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, Color()); return env->ambient_light; } -RS::EnvironmentAmbientSource RasterizerSceneRD::environment_get_ambient_source(RID p_env) const { +RS::EnvironmentAmbientSource RendererSceneRenderRD::environment_get_ambient_source(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG); return env->ambient_source; } -float RasterizerSceneRD::environment_get_ambient_light_energy(RID p_env) const { +float RendererSceneRenderRD::environment_get_ambient_light_energy(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->ambient_light_energy; } -float RasterizerSceneRD::environment_get_ambient_sky_contribution(RID p_env) const { +float RendererSceneRenderRD::environment_get_ambient_sky_contribution(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->ambient_sky_contribution; } -RS::EnvironmentReflectionSource RasterizerSceneRD::environment_get_reflection_source(RID p_env) const { +RS::EnvironmentReflectionSource RendererSceneRenderRD::environment_get_reflection_source(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_DISABLED); return env->reflection_source; } -Color RasterizerSceneRD::environment_get_ao_color(RID p_env) const { +Color RendererSceneRenderRD::environment_get_ao_color(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, Color()); return env->ao_color; } -void RasterizerSceneRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { +void RendererSceneRenderRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->exposure = p_exposure; @@ -2938,7 +2949,7 @@ void RasterizerSceneRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMa env->auto_exp_scale = p_auto_exp_scale; } -void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) { +void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7"); @@ -2954,18 +2965,22 @@ void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, Vector<fl env->glow_hdr_luminance_cap = p_hdr_luminance_cap; } -void RasterizerSceneRD::environment_glow_set_use_bicubic_upscale(bool p_enable) { +void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enable) { glow_bicubic_upscale = p_enable; } -void RasterizerSceneRD::environment_glow_set_use_high_quality(bool p_enable) { +void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable) { glow_high_quality = p_enable; } -void RasterizerSceneRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { +void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); + if (low_end) { + return; + } + env->sdfgi_enabled = p_enable; env->sdfgi_cascades = p_cascades; env->sdfgi_min_cell_size = p_min_cell_size; @@ -2978,7 +2993,7 @@ void RasterizerSceneRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::Envi env->sdfgi_y_scale = p_y_scale; } -void RasterizerSceneRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) { +void RendererSceneRenderRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -2992,54 +3007,58 @@ void RasterizerSceneRD::environment_set_fog(RID p_env, bool p_enable, const Colo env->fog_aerial_perspective = p_fog_aerial_perspective; } -bool RasterizerSceneRD::environment_is_fog_enabled(RID p_env) const { +bool RendererSceneRenderRD::environment_is_fog_enabled(RID p_env) const { const Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, false); return env->fog_enabled; } -Color RasterizerSceneRD::environment_get_fog_light_color(RID p_env) const { +Color RendererSceneRenderRD::environment_get_fog_light_color(RID p_env) const { const Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, Color()); return env->fog_light_color; } -float RasterizerSceneRD::environment_get_fog_light_energy(RID p_env) const { +float RendererSceneRenderRD::environment_get_fog_light_energy(RID p_env) const { const Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->fog_light_energy; } -float RasterizerSceneRD::environment_get_fog_sun_scatter(RID p_env) const { +float RendererSceneRenderRD::environment_get_fog_sun_scatter(RID p_env) const { const Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->fog_sun_scatter; } -float RasterizerSceneRD::environment_get_fog_density(RID p_env) const { +float RendererSceneRenderRD::environment_get_fog_density(RID p_env) const { const Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->fog_density; } -float RasterizerSceneRD::environment_get_fog_height(RID p_env) const { +float RendererSceneRenderRD::environment_get_fog_height(RID p_env) const { const Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->fog_height; } -float RasterizerSceneRD::environment_get_fog_height_density(RID p_env) const { +float RendererSceneRenderRD::environment_get_fog_height_density(RID p_env) const { const Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->fog_height_density; } -float RasterizerSceneRD::environment_get_fog_aerial_perspective(RID p_env) const { +float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) const { const Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, 0); return env->fog_aerial_perspective; } -void RasterizerSceneRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RenderingServer::EnvVolumetricFogShadowFilter p_shadow_filter) { +void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RenderingServer::EnvVolumetricFogShadowFilter p_shadow_filter) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); + if (low_end) { + return; + } + env->volumetric_fog_enabled = p_enable; env->volumetric_fog_density = p_density; env->volumetric_fog_light = p_light; @@ -3050,15 +3069,15 @@ void RasterizerSceneRD::environment_set_volumetric_fog(RID p_env, bool p_enable, env->volumetric_fog_gi_inject = p_gi_inject; } -void RasterizerSceneRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) { +void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) { volumetric_fog_size = p_size; volumetric_fog_depth = p_depth; } -void RasterizerSceneRD::environment_set_volumetric_fog_filter_active(bool p_enable) { +void RendererSceneRenderRD::environment_set_volumetric_fog_filter_active(bool p_enable) { volumetric_fog_filter_active = p_enable; } -void RasterizerSceneRD::environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) { +void RendererSceneRenderRD::environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) { p_shrink_size = nearest_power_of_2_templated(p_shrink_size); if (volumetric_fog_directional_shadow_shrink == (uint32_t)p_shrink_size) { return; @@ -3066,7 +3085,7 @@ void RasterizerSceneRD::environment_set_volumetric_fog_directional_shadow_shrink _clear_shadow_shrink_stages(directional_shadow.shrink_stages); } -void RasterizerSceneRD::environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) { +void RendererSceneRenderRD::environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) { p_shrink_size = nearest_power_of_2_templated(p_shrink_size); if (volumetric_fog_positional_shadow_shrink == (uint32_t)p_shrink_size) { return; @@ -3078,18 +3097,22 @@ void RasterizerSceneRD::environment_set_volumetric_fog_positional_shadow_shrink_ } } -void RasterizerSceneRD::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) { +void RendererSceneRenderRD::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) { sdfgi_ray_count = p_ray_count; } -void RasterizerSceneRD::environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) { +void RendererSceneRenderRD::environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) { sdfgi_frames_to_converge = p_frames; } -void RasterizerSceneRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { +void RendererSceneRenderRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); + if (low_end) { + return; + } + env->ssr_enabled = p_enable; env->ssr_max_steps = p_max_steps; env->ssr_fade_in = p_fade_int; @@ -3097,66 +3120,76 @@ void RasterizerSceneRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_ env->ssr_depth_tolerance = p_depth_tolerance; } -void RasterizerSceneRD::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { +void RendererSceneRenderRD::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) { ssr_roughness_quality = p_quality; } -RS::EnvironmentSSRRoughnessQuality RasterizerSceneRD::environment_get_ssr_roughness_quality() const { +RS::EnvironmentSSRRoughnessQuality RendererSceneRenderRD::environment_get_ssr_roughness_quality() const { return ssr_roughness_quality; } -void RasterizerSceneRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { +void RendererSceneRenderRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); + if (low_end) { + return; + } + env->ssao_enabled = p_enable; env->ssao_radius = p_radius; env->ssao_intensity = p_intensity; - env->ssao_bias = p_bias; + env->ssao_power = p_power; + env->ssao_detail = p_detail; + env->ssao_horizon = p_horizon; + env->ssao_sharpness = p_sharpness; env->ssao_direct_light_affect = p_light_affect; env->ssao_ao_channel_affect = p_ao_channel_affect; - env->ssao_blur = p_blur; } -void RasterizerSceneRD::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) { +void RendererSceneRenderRD::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) { ssao_quality = p_quality; ssao_half_size = p_half_size; + ssao_adaptive_target = p_adaptive_target; + ssao_blur_passes = p_blur_passes; + ssao_fadeout_from = p_fadeout_from; + ssao_fadeout_to = p_fadeout_to; } -bool RasterizerSceneRD::environment_is_ssao_enabled(RID p_env) const { +bool RendererSceneRenderRD::environment_is_ssao_enabled(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, false); return env->ssao_enabled; } -float RasterizerSceneRD::environment_get_ssao_ao_affect(RID p_env) const { +float RendererSceneRenderRD::environment_get_ssao_ao_affect(RID p_env) const { Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, false); + ERR_FAIL_COND_V(!env, 0.0); return env->ssao_ao_channel_affect; } -float RasterizerSceneRD::environment_get_ssao_light_affect(RID p_env) const { +float RendererSceneRenderRD::environment_get_ssao_light_affect(RID p_env) const { Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, false); + ERR_FAIL_COND_V(!env, 0.0); return env->ssao_direct_light_affect; } -bool RasterizerSceneRD::environment_is_ssr_enabled(RID p_env) const { +bool RendererSceneRenderRD::environment_is_ssr_enabled(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, false); return env->ssr_enabled; } -bool RasterizerSceneRD::environment_is_sdfgi_enabled(RID p_env) const { +bool RendererSceneRenderRD::environment_is_sdfgi_enabled(RID p_env) const { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, false); return env->sdfgi_enabled; } -bool RasterizerSceneRD::is_environment(RID p_env) const { +bool RendererSceneRenderRD::is_environment(RID p_env) const { return environment_owner.owns(p_env); } -Ref<Image> RasterizerSceneRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) { +Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND_V(!env, Ref<Image>()); @@ -3195,7 +3228,7 @@ Ref<Image> RasterizerSceneRD::environment_bake_panorama(RID p_env, bool p_bake_i //////////////////////////////////////////////////////////// -RID RasterizerSceneRD::reflection_atlas_create() { +RID RendererSceneRenderRD::reflection_atlas_create() { ReflectionAtlas ra; ra.count = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_count"); ra.size = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_size"); @@ -3203,7 +3236,7 @@ RID RasterizerSceneRD::reflection_atlas_create() { return reflection_atlas_owner.make_rid(ra); } -void RasterizerSceneRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) { +void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) { ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas); ERR_FAIL_COND(!ra); @@ -3234,14 +3267,21 @@ void RasterizerSceneRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflect } } +int RendererSceneRenderRD::reflection_atlas_get_size(RID p_ref_atlas) const { + ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas); + ERR_FAIL_COND_V(!ra, 0); + + return ra->size; +} + //////////////////////// -RID RasterizerSceneRD::reflection_probe_instance_create(RID p_probe) { +RID RendererSceneRenderRD::reflection_probe_instance_create(RID p_probe) { ReflectionProbeInstance rpi; rpi.probe = p_probe; return reflection_probe_instance_owner.make_rid(rpi); } -void RasterizerSceneRD::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) { +void RendererSceneRenderRD::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND(!rpi); @@ -3249,7 +3289,7 @@ void RasterizerSceneRD::reflection_probe_instance_set_transform(RID p_instance, rpi->dirty = true; } -void RasterizerSceneRD::reflection_probe_release_atlas_index(RID p_instance) { +void RendererSceneRenderRD::reflection_probe_release_atlas_index(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND(!rpi); @@ -3264,7 +3304,7 @@ void RasterizerSceneRD::reflection_probe_release_atlas_index(RID p_instance) { rpi->atlas = RID(); } -bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) { +bool RendererSceneRenderRD::reflection_probe_instance_needs_redraw(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, false); @@ -3283,14 +3323,14 @@ bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) { return rpi->atlas_index == -1; } -bool RasterizerSceneRD::reflection_probe_instance_has_reflection(RID p_instance) { +bool RendererSceneRenderRD::reflection_probe_instance_has_reflection(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, false); return rpi->atlas.is_valid(); } -bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { +bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_reflection_atlas); ERR_FAIL_COND_V(!atlas, false); @@ -3326,7 +3366,7 @@ bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, R RD::TextureFormat tf; tf.array_layers = 6 * atlas->count; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY; + tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; tf.mipmaps = mipmaps; tf.width = atlas->size; tf.height = atlas->size; @@ -3389,7 +3429,7 @@ bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, R return true; } -bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instance) { +bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, false); ERR_FAIL_COND_V(!rpi->rendering, false); @@ -3435,7 +3475,7 @@ bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instanc return false; } -uint32_t RasterizerSceneRD::reflection_probe_instance_get_resolution(RID p_instance) { +uint32_t RendererSceneRenderRD::reflection_probe_instance_get_resolution(RID p_instance) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, 0); @@ -3444,7 +3484,7 @@ uint32_t RasterizerSceneRD::reflection_probe_instance_get_resolution(RID p_insta return atlas->size; } -RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) { +RID RendererSceneRenderRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, RID()); ERR_FAIL_INDEX_V(p_index, 6, RID()); @@ -3454,7 +3494,7 @@ RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance, return atlas->reflections[rpi->atlas_index].fbs[p_index]; } -RID RasterizerSceneRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) { +RID RendererSceneRenderRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) { ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, RID()); ERR_FAIL_INDEX_V(p_index, 6, RID()); @@ -3466,11 +3506,11 @@ RID RasterizerSceneRD::reflection_probe_instance_get_depth_framebuffer(RID p_ins /////////////////////////////////////////////////////////// -RID RasterizerSceneRD::shadow_atlas_create() { +RID RendererSceneRenderRD::shadow_atlas_create() { return shadow_atlas_owner.make_rid(ShadowAtlas()); } -void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) { +void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); ERR_FAIL_COND(!shadow_atlas); ERR_FAIL_COND(p_size < 0); @@ -3515,7 +3555,7 @@ void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) { } } -void RasterizerSceneRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { +void RendererSceneRenderRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); ERR_FAIL_COND(!shadow_atlas); ERR_FAIL_INDEX(p_quadrant, 4); @@ -3577,7 +3617,7 @@ void RasterizerSceneRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p } while (swaps > 0); } -bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { +bool RendererSceneRenderRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { for (int i = p_quadrant_count - 1; i >= 0; i--) { int qidx = p_in_quadrants[i]; @@ -3632,7 +3672,7 @@ bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int return false; } -bool RasterizerSceneRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { +bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); ERR_FAIL_COND_V(!shadow_atlas, false); @@ -3767,7 +3807,7 @@ bool RasterizerSceneRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intan return false; } -void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) { +void RendererSceneRenderRD::directional_shadow_atlas_set_size(int p_size) { p_size = nearest_power_of_2_templated(p_size); if (directional_shadow.size == p_size) { @@ -3795,7 +3835,7 @@ void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) { _base_uniforms_changed(); } -void RasterizerSceneRD::set_directional_shadow_count(int p_count) { +void RendererSceneRenderRD::set_directional_shadow_count(int p_count) { directional_shadow.light_count = p_count; directional_shadow.current_light = 0; } @@ -3822,7 +3862,7 @@ static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p return rect; } -int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) { +int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance) { ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0); Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0); @@ -3846,20 +3886,20 @@ int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) { ////////////////////////////////////////////////// -RID RasterizerSceneRD::camera_effects_create() { +RID RendererSceneRenderRD::camera_effects_create() { return camera_effects_owner.make_rid(CameraEffects()); } -void RasterizerSceneRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) { +void RendererSceneRenderRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) { dof_blur_quality = p_quality; dof_blur_use_jitter = p_use_jitter; } -void RasterizerSceneRD::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) { +void RendererSceneRenderRD::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) { dof_blur_bokeh_shape = p_shape; } -void RasterizerSceneRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) { +void RendererSceneRenderRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) { CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); ERR_FAIL_COND(!camfx); @@ -3874,7 +3914,7 @@ void RasterizerSceneRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p camfx->dof_blur_amount = p_amount; } -void RasterizerSceneRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) { +void RendererSceneRenderRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) { CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); ERR_FAIL_COND(!camfx); @@ -3882,7 +3922,7 @@ void RasterizerSceneRD::camera_effects_set_custom_exposure(RID p_camera_effects, camfx->override_exposure = p_exposure; } -RID RasterizerSceneRD::light_instance_create(RID p_light) { +RID RendererSceneRenderRD::light_instance_create(RID p_light) { RID li = light_instance_owner.make_rid(LightInstance()); LightInstance *light_instance = light_instance_owner.getornull(li); @@ -3894,21 +3934,21 @@ RID RasterizerSceneRD::light_instance_create(RID p_light) { return li; } -void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) { +void RendererSceneRenderRD::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) { LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); ERR_FAIL_COND(!light_instance); light_instance->transform = p_transform; } -void RasterizerSceneRD::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) { +void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) { LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); ERR_FAIL_COND(!light_instance); light_instance->aabb = p_aabb; } -void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { +void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); ERR_FAIL_COND(!light_instance); @@ -3928,14 +3968,14 @@ void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance light_instance->shadow_transform[p_pass].uv_scale = p_uv_scale; } -void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) { +void RendererSceneRenderRD::light_instance_mark_visible(RID p_light_instance) { LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); ERR_FAIL_COND(!light_instance); light_instance->last_scene_pass = scene_pass; } -RasterizerSceneRD::ShadowCubemap *RasterizerSceneRD::_get_shadow_cubemap(int p_size) { +RendererSceneRenderRD::ShadowCubemap *RendererSceneRenderRD::_get_shadow_cubemap(int p_size) { if (!shadow_cubemaps.has(p_size)) { ShadowCubemap sc; { @@ -3943,7 +3983,7 @@ RasterizerSceneRD::ShadowCubemap *RasterizerSceneRD::_get_shadow_cubemap(int p_s tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; tf.width = p_size; tf.height = p_size; - tf.type = RD::TEXTURE_TYPE_CUBE; + tf.texture_type = RD::TEXTURE_TYPE_CUBE; tf.array_layers = 6; tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; sc.cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -3962,7 +4002,7 @@ RasterizerSceneRD::ShadowCubemap *RasterizerSceneRD::_get_shadow_cubemap(int p_s return &shadow_cubemaps[p_size]; } -RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p_size) { +RendererSceneRenderRD::ShadowMap *RendererSceneRenderRD::_get_shadow_map(const Size2i &p_size) { if (!shadow_maps.has(p_size)) { ShadowMap sm; { @@ -3987,13 +4027,13 @@ RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p ////////////////////////// -RID RasterizerSceneRD::decal_instance_create(RID p_decal) { +RID RendererSceneRenderRD::decal_instance_create(RID p_decal) { DecalInstance di; di.decal = p_decal; return decal_instance_owner.make_rid(di); } -void RasterizerSceneRD::decal_instance_set_transform(RID p_decal, const Transform &p_transform) { +void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Transform &p_transform) { DecalInstance *di = decal_instance_owner.getornull(p_decal); ERR_FAIL_COND(!di); di->transform = p_transform; @@ -4001,32 +4041,53 @@ void RasterizerSceneRD::decal_instance_set_transform(RID p_decal, const Transfor ///////////////////////////////// -RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) { +RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) { + LightmapInstance li; + li.lightmap = p_lightmap; + return lightmap_instance_owner.make_rid(li); +} +void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) { + LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap); + ERR_FAIL_COND(!li); + li->transform = p_transform; +} + +///////////////////////////////// + +RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) { GIProbeInstance gi_probe; gi_probe.probe = p_base; RID rid = gi_probe_instance_owner.make_rid(gi_probe); return rid; } -void RasterizerSceneRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) { +void RendererSceneRenderRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) { GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); ERR_FAIL_COND(!gi_probe); gi_probe->transform = p_xform; } -bool RasterizerSceneRD::gi_probe_needs_update(RID p_probe) const { +bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const { GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); ERR_FAIL_COND_V(!gi_probe, false); + if (low_end) { + return false; + } + //return true; return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe); } -void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) { +void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) { GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); ERR_FAIL_COND(!gi_probe); + if (low_end) { + return; + } + uint32_t data_version = storage->gi_probe_get_data_version(gi_probe->probe); // (RE)CREATE IF NEEDED @@ -4057,7 +4118,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc tf.width = octree_size.x; tf.height = octree_size.y; tf.depth = octree_size.z; - tf.type = RD::TEXTURE_TYPE_3D; + tf.texture_type = RD::TEXTURE_TYPE_3D; tf.mipmaps = levels.size(); tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; @@ -4088,14 +4149,14 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; u.ids.push_back(storage->gi_probe_get_octree_buffer(gi_probe->probe)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe)); uniforms.push_back(u); @@ -4103,21 +4164,21 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 4; u.ids.push_back(gi_probe->write_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); @@ -4128,7 +4189,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc if (i == 0) { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 3; u.ids.push_back(gi_probe_lights_uniform); copy_uniforms.push_back(u); @@ -4140,7 +4201,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 5; u.ids.push_back(gi_probe->texture); copy_uniforms.push_back(u); @@ -4153,7 +4214,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; u.ids.push_back(mipmap.texture); uniforms.push_back(u); @@ -4227,7 +4288,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 3; u.ids.push_back(gi_probe_lights_uniform); uniforms.push_back(u); @@ -4235,56 +4296,56 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; u.ids.push_back(dmap.albedo); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 6; u.ids.push_back(dmap.normal); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 7; u.ids.push_back(dmap.orm); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 8; u.ids.push_back(dmap.fb_depth); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 11; u.ids.push_back(dmap.texture); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 12; u.ids.push_back(dmap.depth); uniforms.push_back(u); @@ -4300,14 +4361,14 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 5; u.ids.push_back(gi_probe->dynamic_maps[gi_probe->dynamic_maps.size() - 1].texture); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 6; u.ids.push_back(gi_probe->dynamic_maps[gi_probe->dynamic_maps.size() - 1].depth); uniforms.push_back(u); @@ -4316,14 +4377,14 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc if (write) { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 7; u.ids.push_back(dmap.texture); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; u.ids.push_back(dmap.depth); uniforms.push_back(u); @@ -4332,14 +4393,14 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); @@ -4348,14 +4409,17 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc if (plot) { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 11; u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].texture); uniforms.push_back(u); } } - dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT], 0); + dmap.uniform_set = RD::get_singleton()->uniform_set_create( + uniforms, + giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : (write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT)], + 0); } gi_probe->dynamic_maps.push_back(dmap); @@ -4378,7 +4442,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc uint32_t light_count = 0; - if (p_update_light_instances || p_dynamic_object_count > 0) { + if (p_update_light_instances || p_dynamic_objects.size() > 0) { light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size()); { @@ -4392,6 +4456,11 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc RID light = light_instance_get_base_light(light_instance); l.type = storage->light_get_type(light); + if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_is_sky_only(light)) { + light_count--; + continue; + } + l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length(); @@ -4423,7 +4492,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc } } - if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_object_count) { + if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_objects.size()) { // PROCESS MIPMAPS if (gi_probe->mipmaps.size()) { //can update mipmaps @@ -4516,7 +4585,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc gi_probe->has_dynamic_object_data = false; //clear until dynamic object data is used again - if (p_dynamic_object_count && gi_probe->dynamic_maps.size()) { + if (p_dynamic_objects.size() && gi_probe->dynamic_maps.size()) { Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe); int multiplier = gi_probe->dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z); @@ -4530,14 +4599,11 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc AABB probe_aabb(Vector3(), octree_size); //this could probably be better parallelized in compute.. - for (int i = 0; i < p_dynamic_object_count; i++) { - InstanceBase *instance = p_dynamic_objects[i]; - //not used, so clear - instance->depth_layer = 0; - instance->depth = 0; + for (int i = 0; i < (int)p_dynamic_objects.size(); i++) { + GeometryInstance *instance = p_dynamic_objects[i]; //transform aabb to giprobe - AABB aabb = (to_probe_xform * instance->transform).xform(instance->aabb); + AABB aabb = (to_probe_xform * geometry_instance_get_transform(instance)).xform(geometry_instance_get_aabb(instance)); //this needs to wrap to grid resolution to avoid jitter //also extend margin a bit just in case @@ -4601,7 +4667,12 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc CameraMatrix cm; cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]); - _render_material(to_world_xform * xform, cm, true, &instance, 1, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size)); + if (cull_argument.size() == 0) { + cull_argument.push_back(nullptr); + } + cull_argument[0] = instance; + + _render_material(to_world_xform * xform, cm, true, cull_argument, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size)); GIProbeDynamicPushConstant push_constant; zeromem(&push_constant, sizeof(GIProbeDynamicPushConstant)); @@ -4718,7 +4789,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc gi_probe->last_probe_version = storage->gi_probe_get_version(gi_probe->probe); } -void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +void RendererSceneRenderRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); @@ -4754,21 +4825,21 @@ void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_lis Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; u.ids.push_back(gi_probe->texture); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 3; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); @@ -4782,13 +4853,22 @@ void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_lis } giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_debug_shader_version_shaders[0], 0); - RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, giprobe_debug_shader_version_pipelines[p_emission ? GI_PROBE_DEBUG_EMISSION : p_lighting ? (gi_probe->has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT) : GI_PROBE_DEBUG_COLOR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); + + int giprobe_debug_pipeline = GI_PROBE_DEBUG_COLOR; + if (p_emission) { + giprobe_debug_pipeline = GI_PROBE_DEBUG_EMISSION; + } else if (p_lighting) { + giprobe_debug_pipeline = gi_probe->has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT; + } + RD::get_singleton()->draw_list_bind_render_pipeline( + p_draw_list, + giprobe_debug_shader_version_pipelines[giprobe_debug_pipeline].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, giprobe_debug_uniform_set, 0); RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant)); RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36); } -void RasterizerSceneRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { +void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -4827,28 +4907,28 @@ void RasterizerSceneRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID { RD::Uniform u; u.binding = 1; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.ids.push_back(rb->sdfgi->cascades_ubo); uniforms.push_back(u); } { RD::Uniform u; u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.push_back(rb->sdfgi->lightprobe_texture); uniforms.push_back(u); } { RD::Uniform u; u.binding = 3; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; u.binding = 4; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.push_back(rb->sdfgi->occlusion_texture); uniforms.push_back(u); } @@ -4925,13 +5005,13 @@ void RasterizerSceneRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID } //////////////////////////////// -RID RasterizerSceneRD::render_buffers_create() { +RID RendererSceneRenderRD::render_buffers_create() { RenderBuffers rb; rb.data = _create_render_buffer_data(); return render_buffers_owner.make_rid(rb); } -void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) { +void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { ERR_FAIL_COND(!rb->blur[0].texture.is_null()); uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH); @@ -4940,7 +5020,7 @@ void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) { tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = rb->width; tf.height = rb->height; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; tf.mipmaps = mipmaps_required; @@ -4974,7 +5054,7 @@ void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) { } } -void RasterizerSceneRD::_allocate_luminance_textures(RenderBuffers *rb) { +void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) { ERR_FAIL_COND(!rb->luminance.current.is_null()); int w = rb->width; @@ -5007,7 +5087,7 @@ void RasterizerSceneRD::_allocate_luminance_textures(RenderBuffers *rb) { } } -void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) { +void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { if (rb->texture.is_valid()) { RD::get_singleton()->free(rb->texture); rb->texture = RID(); @@ -5040,21 +5120,24 @@ void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) { rb->luminance.current = RID(); } - if (rb->ssao.ao[0].is_valid()) { + if (rb->ssao.depth.is_valid()) { RD::get_singleton()->free(rb->ssao.depth); - RD::get_singleton()->free(rb->ssao.ao[0]); - if (rb->ssao.ao[1].is_valid()) { - RD::get_singleton()->free(rb->ssao.ao[1]); - } - if (rb->ssao.ao_full.is_valid()) { - RD::get_singleton()->free(rb->ssao.ao_full); - } + RD::get_singleton()->free(rb->ssao.ao_deinterleaved); + RD::get_singleton()->free(rb->ssao.ao_pong); + RD::get_singleton()->free(rb->ssao.ao_final); + + RD::get_singleton()->free(rb->ssao.importance_map[0]); + RD::get_singleton()->free(rb->ssao.importance_map[1]); rb->ssao.depth = RID(); - rb->ssao.ao[0] = RID(); - rb->ssao.ao[1] = RID(); - rb->ssao.ao_full = RID(); + rb->ssao.ao_deinterleaved = RID(); + rb->ssao.ao_pong = RID(); + rb->ssao.ao_final = RID(); + rb->ssao.importance_map[0] = RID(); + rb->ssao.importance_map[1] = RID(); rb->ssao.depth_slices.clear(); + rb->ssao.ao_deinterleaved_slices.clear(); + rb->ssao.ao_pong_slices.clear(); } if (rb->ssr.blur_radius[0].is_valid()) { @@ -5072,7 +5155,7 @@ void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) { } } -void RasterizerSceneRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) { +void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -5091,7 +5174,7 @@ void RasterizerSceneRD::_process_sss(RID p_render_buffers, const CameraMatrix &p storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality); } -void RasterizerSceneRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) { +void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -5113,7 +5196,7 @@ void RasterizerSceneRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffe tf.format = RD::DATA_FORMAT_R32_SFLOAT; tf.width = rb->width / 2; tf.height = rb->height / 2; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; rb->ssr.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -5128,7 +5211,7 @@ void RasterizerSceneRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffe tf.format = RD::DATA_FORMAT_R8_UNORM; tf.width = rb->width / 2; tf.height = rb->height / 2; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; rb->ssr.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -5144,7 +5227,7 @@ void RasterizerSceneRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffe storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, rb->blur[0].mipmaps[1].texture); } -void RasterizerSceneRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { +void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -5153,67 +5236,135 @@ void RasterizerSceneRD::_process_ssao(RID p_render_buffers, RID p_environment, R RENDER_TIMESTAMP("Process SSAO"); - if (rb->ssao.ao[0].is_valid() && rb->ssao.ao_full.is_valid() != ssao_half_size) { + if (rb->ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) { RD::get_singleton()->free(rb->ssao.depth); - RD::get_singleton()->free(rb->ssao.ao[0]); - if (rb->ssao.ao[1].is_valid()) { - RD::get_singleton()->free(rb->ssao.ao[1]); - } - if (rb->ssao.ao_full.is_valid()) { - RD::get_singleton()->free(rb->ssao.ao_full); - } + RD::get_singleton()->free(rb->ssao.ao_deinterleaved); + RD::get_singleton()->free(rb->ssao.ao_pong); + RD::get_singleton()->free(rb->ssao.ao_final); + + RD::get_singleton()->free(rb->ssao.importance_map[0]); + RD::get_singleton()->free(rb->ssao.importance_map[1]); rb->ssao.depth = RID(); - rb->ssao.ao[0] = RID(); - rb->ssao.ao[1] = RID(); - rb->ssao.ao_full = RID(); + rb->ssao.ao_deinterleaved = RID(); + rb->ssao.ao_pong = RID(); + rb->ssao.ao_final = RID(); + rb->ssao.importance_map[0] = RID(); + rb->ssao.importance_map[1] = RID(); rb->ssao.depth_slices.clear(); + rb->ssao.ao_deinterleaved_slices.clear(); + rb->ssao.ao_pong_slices.clear(); + } + + int buffer_width; + int buffer_height; + int half_width; + int half_height; + if (ssao_half_size) { + buffer_width = (rb->width + 3) / 4; + buffer_height = (rb->height + 3) / 4; + half_width = (rb->width + 7) / 8; + half_height = (rb->height + 7) / 8; + } else { + buffer_width = (rb->width + 1) / 2; + buffer_height = (rb->height + 1) / 2; + half_width = (rb->width + 3) / 4; + half_height = (rb->height + 3) / 4; } - - if (!rb->ssao.ao[0].is_valid()) { + bool uniform_sets_are_invalid = false; + if (rb->ssao.depth.is_null()) { //allocate depth slices { RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = rb->width / 2; - tf.height = rb->height / 2; - tf.mipmaps = Image::get_image_required_mipmaps(tf.width, tf.height, Image::FORMAT_RF) + 1; + tf.format = RD::DATA_FORMAT_R16_SFLOAT; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = buffer_width; + tf.height = buffer_height; + tf.mipmaps = 4; + tf.array_layers = 4; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; rb->ssao.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); for (uint32_t i = 0; i < tf.mipmaps; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.depth, 0, i); + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.depth, 0, i, RD::TEXTURE_SLICE_2D_ARRAY); rb->ssao.depth_slices.push_back(slice); } } { RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = ssao_half_size ? rb->width / 2 : rb->width; - tf.height = ssao_half_size ? rb->height / 2 : rb->height; + tf.format = RD::DATA_FORMAT_R8G8_UNORM; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = buffer_width; + tf.height = buffer_height; + tf.array_layers = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb->ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView()); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.ao_deinterleaved, i, 0); + rb->ssao.ao_deinterleaved_slices.push_back(slice); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8G8_UNORM; + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.width = buffer_width; + tf.height = buffer_height; + tf.array_layers = 4; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ssao.ao[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->ssao.ao[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView()); + for (uint32_t i = 0; i < 4; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.ao_pong, i, 0); + rb->ssao.ao_pong_slices.push_back(slice); + } } - if (ssao_half_size) { - //upsample texture + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = half_width; + tf.height = half_height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb->ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8_UNORM; tf.width = rb->width; tf.height = rb->height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ssao.ao_full = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView()); + _render_buffers_uniform_set_changed(p_render_buffers); } - - _render_buffers_uniform_set_changed(p_render_buffers); + ssao_using_half_size = ssao_half_size; + uniform_sets_are_invalid = true; } - storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, Size2i(rb->width, rb->height), rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao[0], rb->ssao.ao_full.is_valid(), rb->ssao.ao[1], rb->ssao.ao_full, env->ssao_intensity, env->ssao_radius, env->ssao_bias, p_projection, ssao_quality, env->ssao_blur, env->ssao_blur_edge_sharpness); + EffectsRD::SSAOSettings settings; + settings.radius = env->ssao_radius; + settings.intensity = env->ssao_intensity; + settings.power = env->ssao_power; + settings.detail = env->ssao_detail; + settings.horizon = env->ssao_horizon; + settings.sharpness = env->ssao_sharpness; + + settings.quality = ssao_quality; + settings.half_size = ssao_half_size; + settings.adaptive_target = ssao_adaptive_target; + settings.blur_passes = ssao_blur_passes; + settings.fadeout_from = ssao_fadeout_from; + settings.fadeout_to = ssao_fadeout_to; + settings.full_screen_size = Size2i(rb->width, rb->height); + settings.half_screen_size = Size2i(buffer_width, buffer_height); + settings.quarter_screen_size = Size2i(half_width, half_height); + + storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid); } -void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection) { +void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -5247,7 +5398,7 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu //swap final reduce with prev luminance SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); - RenderingServerRaster::redraw_request(); //redraw all the time if auto exposure rendering is on + RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on } int max_glow_level = -1; @@ -5288,21 +5439,19 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu { //tonemap - RasterizerEffectsRD::TonemapSettings tonemap; - - tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + EffectsRD::TonemapSettings tonemap; if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) { tonemap.use_auto_exposure = true; tonemap.exposure_texture = rb->luminance.current; tonemap.auto_exposure_grey = env->auto_exp_scale; } else { - tonemap.exposure_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + tonemap.exposure_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); } if (can_use_effects && env && env->glow_enabled) { tonemap.use_glow = true; - tonemap.glow_mode = RasterizerEffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode); + tonemap.glow_mode = EffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode); tonemap.glow_intensity = env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity; for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { tonemap.glow_levels[i] = env->glow_levels[i]; @@ -5312,7 +5461,7 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; tonemap.glow_texture = rb->blur[1].texture; } else { - tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + tonemap.glow_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); } if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { @@ -5328,14 +5477,30 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu tonemap.exposure = env->exposure; } + tonemap.use_color_correction = false; + tonemap.use_1d_color_correction = false; + tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + + if (can_use_effects && env) { + tonemap.use_bcs = env->adjustments_enabled; + tonemap.brightness = env->adjustments_brightness; + tonemap.contrast = env->adjustments_contrast; + tonemap.saturation = env->adjustments_saturation; + if (env->adjustments_enabled && env->color_correction.is_valid()) { + tonemap.use_color_correction = true; + tonemap.use_1d_color_correction = env->use_1d_color_correction; + tonemap.color_correction_texture = storage->texture_get_rd_texture(env->color_correction); + } + } + storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); } storage->render_target_disable_clear_request(rb->render_target); } -void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas) { - RasterizerEffectsRD *effects = storage->get_effects(); +void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas) { + EffectsRD *effects = storage->get_effects(); RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -5376,9 +5541,9 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s } } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ssao.ao[0].is_valid()) { + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ssao.ao_final.is_valid()) { Size2 rtsize = storage->render_target_get_size(rb->render_target); - RID ao_buf = rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; + RID ao_buf = rb->ssao.ao_final; effects->copy_to_fb_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); } @@ -5395,7 +5560,19 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s } } -void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform) { +void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) { + Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->adjustments_enabled = p_enable; + env->adjustments_brightness = p_brightness; + env->adjustments_contrast = p_contrast; + env->adjustments_saturation = p_saturation; + env->use_1d_color_correction = p_use_1d_color_correction; + env->color_correction = p_color_correction; +} + +void RendererSceneRenderRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -5408,12 +5585,12 @@ void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatr { RD::Uniform u; u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { if (i < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[i].sdf_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -5421,12 +5598,12 @@ void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatr { RD::Uniform u; u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { if (i < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[i].light_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -5434,12 +5611,12 @@ void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatr { RD::Uniform u; u.binding = 3; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { if (i < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[i].light_aniso_0_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -5447,12 +5624,12 @@ void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatr { RD::Uniform u; u.binding = 4; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { if (i < rb->sdfgi->cascades.size()) { u.ids.push_back(rb->sdfgi->cascades[i].light_aniso_1_tex); } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -5460,35 +5637,35 @@ void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatr { RD::Uniform u; u.binding = 5; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.push_back(rb->sdfgi->occlusion_texture); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); } { RD::Uniform u; u.binding = 9; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.ids.push_back(rb->sdfgi->cascades_ubo); uniforms.push_back(u); } { RD::Uniform u; u.binding = 10; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.ids.push_back(rb->texture); uniforms.push_back(u); } { RD::Uniform u; u.binding = 11; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.push_back(rb->sdfgi->lightprobe_texture); uniforms.push_back(u); } @@ -5541,7 +5718,7 @@ void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatr storage->get_effects()->copy_to_fb_rect(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), true); } -RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) { +RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); if (!rb->blur[0].texture.is_valid()) { @@ -5550,14 +5727,14 @@ RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffe return rb->blur[0].texture; } -RID RasterizerSceneRD::render_buffers_get_ao_texture(RID p_render_buffers) { +RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); - return rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; + return rb->ssao.ao_final; } -RID RasterizerSceneRD::render_buffers_get_gi_probe_buffer(RID p_render_buffers) { +RID RendererSceneRenderRD::render_buffers_get_gi_probe_buffer(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); if (rb->giprobe_buffer.is_null()) { @@ -5566,24 +5743,24 @@ RID RasterizerSceneRD::render_buffers_get_gi_probe_buffer(RID p_render_buffers) return rb->giprobe_buffer; } -RID RasterizerSceneRD::render_buffers_get_default_gi_probe_buffer() { +RID RendererSceneRenderRD::render_buffers_get_default_gi_probe_buffer() { return default_giprobe_buffer; } -uint32_t RasterizerSceneRD::render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const { +uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, 0); ERR_FAIL_COND_V(!rb->sdfgi, 0); return rb->sdfgi->cascades.size(); } -bool RasterizerSceneRD::render_buffers_is_sdfgi_enabled(RID p_render_buffers) const { +bool RendererSceneRenderRD::render_buffers_is_sdfgi_enabled(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, false); return rb->sdfgi != nullptr; } -RID RasterizerSceneRD::render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const { +RID RendererSceneRenderRD::render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); ERR_FAIL_COND_V(!rb->sdfgi, RID()); @@ -5591,7 +5768,7 @@ RID RasterizerSceneRD::render_buffers_get_sdfgi_irradiance_probes(RID p_render_b return rb->sdfgi->lightprobe_texture; } -Vector3 RasterizerSceneRD::render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const { +Vector3 RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, Vector3()); ERR_FAIL_COND_V(!rb->sdfgi, Vector3()); @@ -5600,7 +5777,7 @@ Vector3 RasterizerSceneRD::render_buffers_get_sdfgi_cascade_offset(RID p_render_ return Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[p_cascade].position)) * rb->sdfgi->cascades[p_cascade].cell_size; } -Vector3i RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const { +Vector3i RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, Vector3i()); ERR_FAIL_COND_V(!rb->sdfgi, Vector3i()); @@ -5610,14 +5787,14 @@ Vector3i RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_offset(RID p_ return rb->sdfgi->cascades[p_cascade].position / probe_divisor; } -float RasterizerSceneRD::render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const { +float RendererSceneRenderRD::render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, 0); ERR_FAIL_COND_V(!rb->sdfgi, 0); return rb->sdfgi->normal_bias; } -float RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const { +float RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, 0); ERR_FAIL_COND_V(!rb->sdfgi, 0); @@ -5625,7 +5802,7 @@ float RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_size(RID p_rende return float(rb->sdfgi->cascade_size) * rb->sdfgi->cascades[p_cascade].cell_size / float(rb->sdfgi->probe_axis_count - 1); } -uint32_t RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const { +uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, 0); ERR_FAIL_COND_V(!rb->sdfgi, 0); @@ -5633,7 +5810,7 @@ uint32_t RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_count(RID p_r return rb->sdfgi->probe_axis_count; } -uint32_t RasterizerSceneRD::render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const { +uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, 0); ERR_FAIL_COND_V(!rb->sdfgi, 0); @@ -5641,7 +5818,7 @@ uint32_t RasterizerSceneRD::render_buffers_get_sdfgi_cascade_size(RID p_render_b return rb->sdfgi->cascade_size; } -bool RasterizerSceneRD::render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const { +bool RendererSceneRenderRD::render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, false); ERR_FAIL_COND_V(!rb->sdfgi, false); @@ -5649,14 +5826,14 @@ bool RasterizerSceneRD::render_buffers_is_sdfgi_using_occlusion(RID p_render_buf return rb->sdfgi->uses_occlusion; } -float RasterizerSceneRD::render_buffers_get_sdfgi_energy(RID p_render_buffers) const { +float RendererSceneRenderRD::render_buffers_get_sdfgi_energy(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND_V(!rb, 0); - ERR_FAIL_COND_V(!rb->sdfgi, false); + ERR_FAIL_COND_V(!rb, 0.0); + ERR_FAIL_COND_V(!rb->sdfgi, 0.0); return rb->sdfgi->energy; } -RID RasterizerSceneRD::render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const { +RID RendererSceneRenderRD::render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); ERR_FAIL_COND_V(!rb->sdfgi, RID()); @@ -5664,20 +5841,20 @@ RID RasterizerSceneRD::render_buffers_get_sdfgi_occlusion_texture(RID p_render_b return rb->sdfgi->occlusion_texture; } -bool RasterizerSceneRD::render_buffers_has_volumetric_fog(RID p_render_buffers) const { +bool RendererSceneRenderRD::render_buffers_has_volumetric_fog(RID p_render_buffers) const { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, false); return rb->volumetric_fog != nullptr; } -RID RasterizerSceneRD::render_buffers_get_volumetric_fog_texture(RID p_render_buffers) { +RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_texture(RID p_render_buffers) { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, RID()); return rb->volumetric_fog->fog_map; } -RID RasterizerSceneRD::render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers) { +RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers) { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); @@ -5688,18 +5865,18 @@ RID RasterizerSceneRD::render_buffers_get_volumetric_fog_sky_uniform_set(RID p_r return rb->volumetric_fog->sky_uniform_set; } -float RasterizerSceneRD::render_buffers_get_volumetric_fog_end(RID p_render_buffers) { +float RendererSceneRenderRD::render_buffers_get_volumetric_fog_end(RID p_render_buffers) { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, 0); return rb->volumetric_fog->length; } -float RasterizerSceneRD::render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers) { +float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers) { const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, 0); return rb->volumetric_fog->spread; } -void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) { +void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); rb->width = p_width; rb->height = p_height; @@ -5749,20 +5926,20 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren _render_buffers_uniform_set_changed(p_render_buffers); } -void RasterizerSceneRD::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) { +void RendererSceneRenderRD::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) { sss_quality = p_quality; } -RS::SubSurfaceScatteringQuality RasterizerSceneRD::sub_surface_scattering_get_quality() const { +RS::SubSurfaceScatteringQuality RendererSceneRenderRD::sub_surface_scattering_get_quality() const { return sss_quality; } -void RasterizerSceneRD::sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) { +void RendererSceneRenderRD::sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) { sss_scale = p_scale; sss_depth_scale = p_depth_scale; } -void RasterizerSceneRD::shadows_quality_set(RS::ShadowQuality p_quality) { +void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) { ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); if (shadows_quality != p_quality) { @@ -5802,7 +5979,7 @@ void RasterizerSceneRD::shadows_quality_set(RS::ShadowQuality p_quality) { } } -void RasterizerSceneRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) { +void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) { ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); if (directional_shadow_quality != p_quality) { @@ -5842,25 +6019,25 @@ void RasterizerSceneRD::directional_shadow_quality_set(RS::ShadowQuality p_quali } } -int RasterizerSceneRD::get_roughness_layers() const { +int RendererSceneRenderRD::get_roughness_layers() const { return roughness_layers; } -bool RasterizerSceneRD::is_using_radiance_cubemap_array() const { +bool RendererSceneRenderRD::is_using_radiance_cubemap_array() const { return sky_use_cubemap_array; } -RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data(RID p_render_buffers) { +RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_get_data(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND_V(!rb, nullptr); return rb->data; } -void RasterizerSceneRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) { - for (int i = 0; i < p_reflection_probe_cull_count; i++) { - RID rpi = p_reflection_probe_cull_result[i]; +void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment) { + for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) { + RID rpi = p_reflections[i]; - if (i >= (int)cluster.max_reflections) { + if (i >= cluster.max_reflections) { reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set continue; } @@ -5904,26 +6081,26 @@ void RasterizerSceneRD::_setup_reflections(RID *p_reflection_probe_cull_result, Transform transform = reflection_probe_instance_get_transform(rpi); Transform proj = (p_camera_inverse_transform * transform).inverse(); - RasterizerStorageRD::store_transform(proj, reflection_ubo.local_matrix); + RendererStorageRD::store_transform(proj, reflection_ubo.local_matrix); cluster.builder.add_reflection_probe(transform, extents); reflection_probe_instance_set_render_pass(rpi, RSG::rasterizer->get_frame_number()); } - if (p_reflection_probe_cull_count) { - RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, MIN(cluster.max_reflections, (unsigned int)p_reflection_probe_cull_count) * sizeof(ReflectionData), cluster.reflections, true); + if (p_reflections.size()) { + RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, MIN(cluster.max_reflections, (unsigned int)p_reflections.size()) * sizeof(ReflectionData), cluster.reflections, true); } } -void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) { +void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) { uint32_t light_count = 0; r_directional_light_count = 0; r_positional_light_count = 0; sky_scene_state.ubo.directional_light_count = 0; - for (int i = 0; i < p_light_cull_count; i++) { - RID li = p_light_cull_result[i]; + for (int i = 0; i < (int)p_lights.size(); i++) { + RID li = p_lights[i]; RID base = light_instance_get_base_light(li); ERR_CONTINUE(base.is_null()); @@ -5931,7 +6108,40 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull RS::LightType type = storage->light_get_type(base); switch (type) { case RS::LIGHT_DIRECTIONAL: { - if (r_directional_light_count >= cluster.max_directional_lights) { + // Copy to SkyDirectionalLightData + if (r_directional_light_count < sky_scene_state.max_directional_lights) { + SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count]; + Transform light_transform = light_instance_get_base_transform(li); + Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); + + sky_light_data.direction[0] = world_direction.x; + sky_light_data.direction[1] = world_direction.y; + sky_light_data.direction[2] = -world_direction.z; + + float sign = storage->light_is_negative(base) ? -1 : 1; + sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); + + Color linear_col = storage->light_get_color(base).to_linear(); + sky_light_data.color[0] = linear_col.r; + sky_light_data.color[1] = linear_col.g; + sky_light_data.color[2] = linear_col.b; + + sky_light_data.enabled = true; + + float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); + if (angular_diameter > 0.0) { + // I know tan(0) is 0, but let's not risk it with numerical precision. + // technically this will keep expanding until reaching the sun, but all we care + // is expand until we reach the radius of the near plane (there can't be more occluders than that) + angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + } else { + angular_diameter = 0.0; + } + sky_light_data.size = angular_diameter; + sky_scene_state.ubo.directional_light_count++; + } + + if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_is_sky_only(base)) { continue; } @@ -6037,7 +6247,7 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale; light_data.shadow_z_range[j] = light_instance_get_shadow_range(li, j); light_data.shadow_range_begin[j] = light_instance_get_shadow_range_begin(li, j); - RasterizerStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]); + RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]); Vector2 uv_scale = light_instance_get_shadow_uv_scale(li, j); uv_scale *= atlas_rect.size; //adapt to atlas size @@ -6074,27 +6284,6 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull } } - // Copy to SkyDirectionalLightData - if (r_directional_light_count < sky_scene_state.max_directional_lights) { - SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count]; - - Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); - - sky_light_data.direction[0] = world_direction.x; - sky_light_data.direction[1] = world_direction.y; - sky_light_data.direction[2] = -world_direction.z; - - sky_light_data.energy = light_data.energy / Math_PI; - - sky_light_data.color[0] = light_data.color[0]; - sky_light_data.color[1] = light_data.color[1]; - sky_light_data.color[2] = light_data.color[2]; - - sky_light_data.enabled = true; - sky_light_data.size = angular_diameter; - sky_scene_state.ubo.directional_light_count++; - } - r_directional_light_count++; } break; case RS::LIGHT_SPOT: @@ -6211,7 +6400,7 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another Transform proj = (p_camera_inverse_transform * light_transform).inverse(); - RasterizerStorageRD::store_transform(proj, light_data.shadow_matrix); + RendererStorageRD::store_transform(proj, light_data.shadow_matrix); if (size > 0.0) { light_data.soft_shadow_size = size; @@ -6226,7 +6415,7 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull bias.set_light_bias(); CameraMatrix shadow_mtx = bias * light_instance_get_shadow_camera(li, 0) * modelview; - RasterizerStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix); + RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix); if (size > 0.0) { CameraMatrix cm = light_instance_get_shadow_camera(li, 0); @@ -6264,15 +6453,15 @@ void RasterizerSceneRD::_setup_lights(RID *p_light_cull_result, int p_light_cull } } -void RasterizerSceneRD::_setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform) { +void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform) { Transform uv_xform; uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0)); uv_xform.origin = Vector3(-1.0, 0.0, -1.0); - p_decal_count = MIN((uint32_t)p_decal_count, cluster.max_decals); + uint32_t decal_count = MIN((uint32_t)p_decals.size(), cluster.max_decals); int idx = 0; - for (int i = 0; i < p_decal_count; i++) { - RID di = p_decal_instances[i]; + for (uint32_t i = 0; i < decal_count; i++) { + RID di = p_decals[i]; RID decal = decal_instance_get_base(di); Transform xform = decal_instance_get_transform(di); @@ -6300,7 +6489,7 @@ void RasterizerSceneRD::_setup_decals(const RID *p_decal_instances, int p_decal_ Transform scale_xform; scale_xform.basis.scale(Vector3(decal_extents.x, decal_extents.y, decal_extents.z)); Transform to_decal_xform = (p_camera_inverse_xform * decal_instance_get_transform(di) * scale_xform * uv_xform).affine_inverse(); - RasterizerStorageRD::store_transform(to_decal_xform, dd.xform); + RendererStorageRD::store_transform(to_decal_xform, dd.xform); Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized(); normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine @@ -6338,7 +6527,7 @@ void RasterizerSceneRD::_setup_decals(const RID *p_decal_instances, int p_decal_ dd.normal_rect[3] = rect.size.y; Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized(); - RasterizerStorageRD::store_basis_3x4(normal_xform, dd.normal_xform); + RendererStorageRD::store_basis_3x4(normal_xform, dd.normal_xform); } else { dd.normal_rect[0] = 0; dd.normal_rect[1] = 0; @@ -6394,7 +6583,7 @@ void RasterizerSceneRD::_setup_decals(const RID *p_decal_instances, int p_decal_ } } -void RasterizerSceneRD::_volumetric_fog_erase(RenderBuffers *rb) { +void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) { ERR_FAIL_COND(!rb->volumetric_fog); RD::get_singleton()->free(rb->volumetric_fog->light_density_map); @@ -6418,7 +6607,7 @@ void RasterizerSceneRD::_volumetric_fog_erase(RenderBuffers *rb) { rb->volumetric_fog = nullptr; } -void RasterizerSceneRD::_allocate_shadow_shrink_stages(RID p_base, int p_base_size, Vector<ShadowShrinkStage> &shrink_stages, uint32_t p_target_size) { +void RendererSceneRenderRD::_allocate_shadow_shrink_stages(RID p_base, int p_base_size, Vector<ShadowShrinkStage> &shrink_stages, uint32_t p_target_size) { //create fog mipmaps uint32_t fog_texture_size = p_target_size; uint32_t base_texture_size = p_base_size; @@ -6451,7 +6640,7 @@ void RasterizerSceneRD::_allocate_shadow_shrink_stages(RID p_base, int p_base_si } } -void RasterizerSceneRD::_clear_shadow_shrink_stages(Vector<ShadowShrinkStage> &shrink_stages) { +void RendererSceneRenderRD::_clear_shadow_shrink_stages(Vector<ShadowShrinkStage> &shrink_stages) { for (int i = 1; i < shrink_stages.size(); i++) { RD::get_singleton()->free(shrink_stages[i].texture); if (shrink_stages[i].filter_texture.is_valid()) { @@ -6461,7 +6650,7 @@ void RasterizerSceneRD::_clear_shadow_shrink_stages(Vector<ShadowShrinkStage> &s shrink_stages.clear(); } -void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count) { +void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_gi_probe_count) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); Environment *env = environment_owner.getornull(p_environment); @@ -6495,7 +6684,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir tf.width = target_width; tf.height = target_height; tf.depth = volumetric_fog_depth; - tf.type = RD::TEXTURE_TYPE_3D; + tf.texture_type = RD::TEXTURE_TYPE_3D; tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -6509,7 +6698,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.ids.push_back(rb->volumetric_fog->fog_map); uniforms.push_back(u); } @@ -6520,7 +6709,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir //update directional shadow if (p_use_directional_shadows) { - if (directional_shadow.shrink_stages.empty()) { + if (directional_shadow.shrink_stages.is_empty()) { if (rb->volumetric_fog->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) { //invalidate uniform set, we will need a new one RD::get_singleton()->free(rb->volumetric_fog->uniform_set); @@ -6555,7 +6744,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir bool force_shrink_shadows = false; - if (shadow_atlas->shrink_stages.empty()) { + if (shadow_atlas->shrink_stages.is_empty()) { if (rb->volumetric_fog->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) { //invalidate uniform set, we will need a new one RD::get_singleton()->free(rb->volumetric_fog->uniform_set); @@ -6682,10 +6871,10 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; if (shadow_atlas == nullptr || shadow_atlas->shrink_stages.size() == 0) { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); } else { u.ids.push_back(shadow_atlas->shrink_stages[shadow_atlas->shrink_stages.size() - 1].texture); } @@ -6695,10 +6884,10 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; if (directional_shadow.shrink_stages.size() == 0) { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); } else { u.ids.push_back(directional_shadow.shrink_stages[directional_shadow.shrink_stages.size() - 1].texture); } @@ -6707,7 +6896,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 3; u.ids.push_back(get_positional_light_buffer()); uniforms.push_back(u); @@ -6715,7 +6904,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 4; u.ids.push_back(get_directional_light_buffer()); uniforms.push_back(u); @@ -6723,7 +6912,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 5; u.ids.push_back(get_cluster_builder_texture()); uniforms.push_back(u); @@ -6731,7 +6920,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 6; u.ids.push_back(get_cluster_builder_indices_buffer()); uniforms.push_back(u); @@ -6739,7 +6928,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 7; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); @@ -6747,7 +6936,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; u.ids.push_back(rb->volumetric_fog->light_density_map); uniforms.push_back(u); @@ -6755,7 +6944,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; u.ids.push_back(rb->volumetric_fog->fog_map); uniforms.push_back(u); @@ -6763,7 +6952,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 10; u.ids.push_back(shadow_sampler); uniforms.push_back(u); @@ -6771,7 +6960,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 11; u.ids.push_back(render_buffers_get_gi_probe_buffer(p_render_buffers)); uniforms.push_back(u); @@ -6779,7 +6968,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 12; for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) { u.ids.push_back(rb->giprobe_textures[i]); @@ -6788,7 +6977,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 13; u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); uniforms.push_back(u); @@ -6809,7 +6998,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 0; u.ids.push_back(gi.sdfgi_ubo); uniforms.push_back(u); @@ -6817,7 +7006,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; u.ids.push_back(rb->sdfgi->ambient_texture); uniforms.push_back(u); @@ -6825,7 +7014,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; u.ids.push_back(rb->sdfgi->occlusion_texture); uniforms.push_back(u); @@ -6940,7 +7129,7 @@ void RasterizerSceneRD::_update_volumetric_fog(RID p_render_buffers, RID p_envir RD::get_singleton()->compute_list_end(); } -void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { +void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) { Color clear_color; if (p_render_buffers.is_valid()) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); @@ -6951,17 +7140,23 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca } //assign render indices to giprobes - for (int i = 0; i < p_gi_probe_cull_count; i++) { - GIProbeInstance *giprobe_inst = gi_probe_instance_owner.getornull(p_gi_probe_cull_result[i]); + for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) { + GIProbeInstance *giprobe_inst = gi_probe_instance_owner.getornull(p_gi_probes[i]); if (giprobe_inst) { giprobe_inst->render_index = i; } } + const PagedArray<RID> *lights = &p_lights; + const PagedArray<RID> *reflections = &p_reflection_probes; + const PagedArray<RID> *gi_probes = &p_gi_probes; + + PagedArray<RID> empty; + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { - p_light_cull_count = 0; - p_reflection_probe_cull_count = 0; - p_gi_probe_cull_count = 0; + lights = ∅ + reflections = ∅ + gi_probes = ∅ } cluster.builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster @@ -6974,17 +7169,17 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca } } else { //do not render reflections when rendering a reflection probe - _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment); + _setup_reflections(*reflections, p_cam_transform.affine_inverse(), p_environment); } uint32_t directional_light_count = 0; uint32_t positional_light_count = 0; - _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows, directional_light_count, positional_light_count); - _setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse()); + _setup_lights(*lights, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows, directional_light_count, positional_light_count); + _setup_decals(p_decals, p_cam_transform.affine_inverse()); cluster.builder.bake_cluster(); //bake to cluster uint32_t gi_probe_count = 0; - _setup_giprobes(p_render_buffers, p_cam_transform, p_gi_probe_cull_result, p_gi_probe_cull_count, gi_probe_count); + _setup_giprobes(p_render_buffers, p_cam_transform, *gi_probes, gi_probe_count); if (p_render_buffers.is_valid()) { bool directional_shadows = false; @@ -6997,7 +7192,7 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca _update_volumetric_fog(p_render_buffers, p_environment, p_cam_projection, p_cam_transform, p_shadow_atlas, directional_light_count, directional_shadows, positional_light_count, gi_probe_count); } - _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, directional_light_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color); + _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, directional_light_count, *gi_probes, p_lightmaps, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold); if (p_render_buffers.is_valid()) { RENDER_TIMESTAMP("Tonemap"); @@ -7010,7 +7205,7 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca } } -void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) { +void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) { LightInstance *light_instance = light_instance_owner.getornull(p_light); ERR_FAIL_COND(!light_instance); @@ -7161,7 +7356,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas if (render_cubemap) { //rendering to cubemap - _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake); + _render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold); if (finalize_cubemap) { //reblit atlas_rect.size.height /= 2; @@ -7172,7 +7367,7 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas } else { //render shadow - _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake); + _render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold); //copy to atlas if (use_linear_depth) { @@ -7186,11 +7381,11 @@ void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pas } } -void RasterizerSceneRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { - _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_framebuffer, p_region); +void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { + _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region); } -void RasterizerSceneRD::render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) { +void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) { //print_line("rendering region " + itos(p_region)); RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -7213,7 +7408,7 @@ void RasterizerSceneRD::render_sdfgi(RID p_render_buffers, int p_region, Instanc } //print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(rb->sdfgi->cascades[cascade].cell_size)); - _render_sdfgi(p_render_buffers, from, size, bounds, p_cull_result, p_cull_count, rb->sdfgi->render_albedo, rb->sdfgi->render_emission, rb->sdfgi->render_emission_aniso, rb->sdfgi->render_geom_facing); + _render_sdfgi(p_render_buffers, from, size, bounds, p_instances, rb->sdfgi->render_albedo, rb->sdfgi->render_emission, rb->sdfgi->render_emission_aniso, rb->sdfgi->render_geom_facing); if (cascade_next != cascade) { RENDER_TIMESTAMP(">SDFGI Update SDF"); @@ -7289,7 +7484,6 @@ void RasterizerSceneRD::render_sdfgi(RID p_render_buffers, int p_region, Instanc ipush_constant.image_size[0] = rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count; ipush_constant.image_size[1] = rb->sdfgi->probe_axis_count; - ipush_constant.image_size[1] = rb->sdfgi->probe_axis_count; int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR; ipush_constant.cascade = cascade; @@ -7528,7 +7722,7 @@ void RasterizerSceneRD::render_sdfgi(RID p_render_buffers, int p_region, Instanc } } -void RasterizerSceneRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count) { +void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) { ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider)); Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale(); CameraMatrix cm; @@ -7542,16 +7736,14 @@ void RasterizerSceneRD::render_particle_collider_heightfield(RID p_collider, con RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider); - _render_particle_collider_heightfield(fb, cam_xform, cm, p_cull_result, p_cull_count); + _render_particle_collider_heightfield(fb, cam_xform, cm, p_instances); } -void RasterizerSceneRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) { +void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); ERR_FAIL_COND(!rb->sdfgi); - ERR_FAIL_COND(p_positional_light_cull_count == 0); - _sdfgi_update_cascades(p_render_buffers); //need cascades updated for this RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -7587,7 +7779,7 @@ void RasterizerSceneRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_ int idx = 0; - for (uint32_t j = 0; j < p_positional_light_cull_count[i]; j++) { + for (uint32_t j = 0; j < (uint32_t)p_positional_light_cull_result[i].size(); j++) { if (idx == SDFGI::MAX_STATIC_LIGHTS) { break; } @@ -7652,7 +7844,7 @@ void RasterizerSceneRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_ RD::get_singleton()->compute_list_end(); } -bool RasterizerSceneRD::free(RID p_rid) { +bool RendererSceneRenderRD::free(RID p_rid) { if (render_buffers_owner.owns(p_rid)) { RenderBuffers *rb = render_buffers_owner.getornull(p_rid); _free_render_buffer_data(rb); @@ -7680,6 +7872,8 @@ bool RasterizerSceneRD::free(RID p_rid) { reflection_probe_instance_owner.free(p_rid); } else if (decal_instance_owner.owns(p_rid)) { decal_instance_owner.free(p_rid); + } else if (lightmap_instance_owner.owns(p_rid)) { + lightmap_instance_owner.free(p_rid); } else if (gi_probe_instance_owner.owns(p_rid)) { GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid); if (gi_probe->texture.is_valid()) { @@ -7751,38 +7945,38 @@ bool RasterizerSceneRD::free(RID p_rid) { return true; } -void RasterizerSceneRD::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) { +void RendererSceneRenderRD::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) { debug_draw = p_debug_draw; } -void RasterizerSceneRD::update() { +void RendererSceneRenderRD::update() { _update_dirty_skys(); } -void RasterizerSceneRD::set_time(double p_time, double p_step) { +void RendererSceneRenderRD::set_time(double p_time, double p_step) { time = p_time; time_step = p_step; } -void RasterizerSceneRD::screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) { +void RendererSceneRenderRD::screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) { screen_space_roughness_limiter = p_enable; screen_space_roughness_limiter_amount = p_amount; screen_space_roughness_limiter_limit = p_limit; } -bool RasterizerSceneRD::screen_space_roughness_limiter_is_active() const { +bool RendererSceneRenderRD::screen_space_roughness_limiter_is_active() const { return screen_space_roughness_limiter; } -float RasterizerSceneRD::screen_space_roughness_limiter_get_amount() const { +float RendererSceneRenderRD::screen_space_roughness_limiter_get_amount() const { return screen_space_roughness_limiter_amount; } -float RasterizerSceneRD::screen_space_roughness_limiter_get_limit() const { +float RendererSceneRenderRD::screen_space_roughness_limiter_get_limit() const { return screen_space_roughness_limiter_limit; } -TypedArray<Image> RasterizerSceneRD::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) { +TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; tf.width = p_image_size.width; // Always 64x64 @@ -7815,19 +8009,27 @@ TypedArray<Image> RasterizerSceneRD::bake_render_uv2(RID p_base, const Vector<RI //RID sampled_light; - InstanceBase ins; + GeometryInstance *gi = geometry_instance_create(p_base); + + uint32_t sc = RSG::storage->mesh_get_surface_count(p_base); + Vector<RID> materials; + materials.resize(sc); - ins.base_type = RSG::storage->get_base_type(p_base); - ins.base = p_base; - ins.materials.resize(RSG::storage->mesh_get_surface_count(p_base)); - for (int i = 0; i < ins.materials.size(); i++) { - if (i < p_material_overrides.size()) { - ins.materials.write[i] = p_material_overrides[i]; + for (uint32_t i = 0; i < sc; i++) { + if (i < (uint32_t)p_material_overrides.size()) { + materials.write[i] = p_material_overrides[i]; } } - InstanceBase *cull = &ins; - _render_uv2(&cull, 1, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height)); + geometry_instance_set_surface_materials(gi, materials); + + if (cull_argument.size() == 0) { + cull_argument.push_back(nullptr); + } + cull_argument[0] = gi; + _render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height)); + + geometry_instance_free(gi); TypedArray<Image> ret; @@ -7873,38 +8075,42 @@ TypedArray<Image> RasterizerSceneRD::bake_render_uv2(RID p_base, const Vector<RI return ret; } -void RasterizerSceneRD::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { +void RendererSceneRenderRD::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { sdfgi_debug_probe_pos = p_position; sdfgi_debug_probe_dir = p_dir; } -RasterizerSceneRD *RasterizerSceneRD::singleton = nullptr; +RendererSceneRenderRD *RendererSceneRenderRD::singleton = nullptr; -RID RasterizerSceneRD::get_cluster_builder_texture() { +RID RendererSceneRenderRD::get_cluster_builder_texture() { return cluster.builder.get_cluster_texture(); } -RID RasterizerSceneRD::get_cluster_builder_indices_buffer() { +RID RendererSceneRenderRD::get_cluster_builder_indices_buffer() { return cluster.builder.get_cluster_indices_buffer(); } -RID RasterizerSceneRD::get_reflection_probe_buffer() { +RID RendererSceneRenderRD::get_reflection_probe_buffer() { return cluster.reflection_buffer; } -RID RasterizerSceneRD::get_positional_light_buffer() { +RID RendererSceneRenderRD::get_positional_light_buffer() { return cluster.light_buffer; } -RID RasterizerSceneRD::get_directional_light_buffer() { +RID RendererSceneRenderRD::get_directional_light_buffer() { return cluster.directional_light_buffer; } -RID RasterizerSceneRD::get_decal_buffer() { +RID RendererSceneRenderRD::get_decal_buffer() { return cluster.decal_buffer; } -int RasterizerSceneRD::get_max_directional_lights() const { +int RendererSceneRenderRD::get_max_directional_lights() const { return cluster.max_directional_lights; } -RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { +bool RendererSceneRenderRD::is_low_end() const { + return low_end; +} + +RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { storage = p_storage; singleton = this; @@ -7913,9 +8119,15 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections"); // sky_use_cubemap_array = false; - //uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); - { + low_end = GLOBAL_GET("rendering/quality/rd_renderer/use_low_end_renderer"); + + if (textures_per_stage < 48) { + low_end = true; + } + + if (!low_end) { //kinda complicated to compute the amount of slots, we try to use as many as we can gi_probe_max_lights = 32; @@ -7944,7 +8156,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { } } - { + if (!low_end) { String defines; Vector<String> versions; versions.push_back("\n#define MODE_DEBUG_COLOR\n"); @@ -7993,8 +8205,8 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { } // register our shader funds - storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); - storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs); + storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); + storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs); { ShaderCompilerRD::DefaultIdentifierActions actions; @@ -8058,7 +8270,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { sky_shader.default_material = storage->material_create(); storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); - SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY); + SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY); sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND); sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO)); @@ -8067,7 +8279,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 0; u.ids.resize(12); RID *ids_ptr = u.ids.ptrw(); @@ -8088,7 +8300,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; u.ids.push_back(storage->global_variables_get_storage_buffer()); uniforms.push_back(u); @@ -8097,7 +8309,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { { RD::Uniform u; u.binding = 2; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.ids.push_back(sky_scene_state.uniform_buffer); uniforms.push_back(u); } @@ -8105,7 +8317,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { { RD::Uniform u; u.binding = 3; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.ids.push_back(sky_scene_state.directional_light_buffer); uniforms.push_back(u); } @@ -8118,8 +8330,8 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { { RD::Uniform u; u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); u.ids.push_back(vfog); uniforms.push_back(u); } @@ -8137,144 +8349,148 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } sky_scene_state.fog_only_texture_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES); } - { - Vector<String> preprocess_modes; - preprocess_modes.push_back("\n#define MODE_SCROLL\n"); - preprocess_modes.push_back("\n#define MODE_SCROLL_OCCLUSION\n"); - preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD\n"); - preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD_HALF\n"); - preprocess_modes.push_back("\n#define MODE_JUMPFLOOD\n"); - preprocess_modes.push_back("\n#define MODE_JUMPFLOOD_OPTIMIZED\n"); - preprocess_modes.push_back("\n#define MODE_UPSCALE_JUMP_FLOOD\n"); - preprocess_modes.push_back("\n#define MODE_OCCLUSION\n"); - preprocess_modes.push_back("\n#define MODE_STORE\n"); - String defines = "\n#define OCCLUSION_SIZE " + itos(SDFGI::CASCADE_SIZE / SDFGI::PROBE_DIVISOR) + "\n"; - sdfgi_shader.preprocess.initialize(preprocess_modes, defines); - sdfgi_shader.preprocess_shader = sdfgi_shader.preprocess.version_create(); - for (int i = 0; i < SDGIShader::PRE_PROCESS_MAX; i++) { - sdfgi_shader.preprocess_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i)); + if (!low_end) { + //SDFGI + { + Vector<String> preprocess_modes; + preprocess_modes.push_back("\n#define MODE_SCROLL\n"); + preprocess_modes.push_back("\n#define MODE_SCROLL_OCCLUSION\n"); + preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD\n"); + preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD_HALF\n"); + preprocess_modes.push_back("\n#define MODE_JUMPFLOOD\n"); + preprocess_modes.push_back("\n#define MODE_JUMPFLOOD_OPTIMIZED\n"); + preprocess_modes.push_back("\n#define MODE_UPSCALE_JUMP_FLOOD\n"); + preprocess_modes.push_back("\n#define MODE_OCCLUSION\n"); + preprocess_modes.push_back("\n#define MODE_STORE\n"); + String defines = "\n#define OCCLUSION_SIZE " + itos(SDFGI::CASCADE_SIZE / SDFGI::PROBE_DIVISOR) + "\n"; + sdfgi_shader.preprocess.initialize(preprocess_modes, defines); + sdfgi_shader.preprocess_shader = sdfgi_shader.preprocess.version_create(); + for (int i = 0; i < SDGIShader::PRE_PROCESS_MAX; i++) { + sdfgi_shader.preprocess_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i)); + } } - } - { - //calculate tables - String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + { + //calculate tables + String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; - Vector<String> direct_light_modes; - direct_light_modes.push_back("\n#define MODE_PROCESS_STATIC\n"); - direct_light_modes.push_back("\n#define MODE_PROCESS_DYNAMIC\n"); - sdfgi_shader.direct_light.initialize(direct_light_modes, defines); - sdfgi_shader.direct_light_shader = sdfgi_shader.direct_light.version_create(); - for (int i = 0; i < SDGIShader::DIRECT_LIGHT_MODE_MAX; i++) { - sdfgi_shader.direct_light_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i)); + Vector<String> direct_light_modes; + direct_light_modes.push_back("\n#define MODE_PROCESS_STATIC\n"); + direct_light_modes.push_back("\n#define MODE_PROCESS_DYNAMIC\n"); + sdfgi_shader.direct_light.initialize(direct_light_modes, defines); + sdfgi_shader.direct_light_shader = sdfgi_shader.direct_light.version_create(); + for (int i = 0; i < SDGIShader::DIRECT_LIGHT_MODE_MAX; i++) { + sdfgi_shader.direct_light_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i)); + } } - } - { - //calculate tables - String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; - defines += "\n#define SH_SIZE " + itos(SDFGI::SH_SIZE) + "\n"; - - Vector<String> integrate_modes; - integrate_modes.push_back("\n#define MODE_PROCESS\n"); - integrate_modes.push_back("\n#define MODE_STORE\n"); - integrate_modes.push_back("\n#define MODE_SCROLL\n"); - integrate_modes.push_back("\n#define MODE_SCROLL_STORE\n"); - sdfgi_shader.integrate.initialize(integrate_modes, defines); - sdfgi_shader.integrate_shader = sdfgi_shader.integrate.version_create(); + { + //calculate tables + String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + defines += "\n#define SH_SIZE " + itos(SDFGI::SH_SIZE) + "\n"; - for (int i = 0; i < SDGIShader::INTEGRATE_MODE_MAX; i++) { - sdfgi_shader.integrate_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i)); - } + Vector<String> integrate_modes; + integrate_modes.push_back("\n#define MODE_PROCESS\n"); + integrate_modes.push_back("\n#define MODE_STORE\n"); + integrate_modes.push_back("\n#define MODE_SCROLL\n"); + integrate_modes.push_back("\n#define MODE_SCROLL_STORE\n"); + sdfgi_shader.integrate.initialize(integrate_modes, defines); + sdfgi_shader.integrate_shader = sdfgi_shader.integrate.version_create(); - { - Vector<RD::Uniform> uniforms; + for (int i = 0; i < SDGIShader::INTEGRATE_MODE_MAX; i++) { + sdfgi_shader.integrate_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i)); + } { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); - uniforms.push_back(u); + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 1; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + + sdfgi_shader.integrate_default_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1); } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 1; - u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); + } + { + //calculate tables + String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + Vector<String> gi_modes; + gi_modes.push_back(""); + gi.shader.initialize(gi_modes, defines); + gi.shader_version = gi.shader.version_create(); + for (int i = 0; i < GI::MODE_MAX; i++) { + gi.pipelines[i] = RD::get_singleton()->compute_pipeline_create(gi.shader.version_get_shader(gi.shader_version, i)); } - sdfgi_shader.integrate_default_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1); + gi.sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(GI::SDFGIData)); } - } - { - //calculate tables - String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; - Vector<String> gi_modes; - gi_modes.push_back(""); - gi.shader.initialize(gi_modes, defines); - gi.shader_version = gi.shader.version_create(); - for (int i = 0; i < GI::MODE_MAX; i++) { - gi.pipelines[i] = RD::get_singleton()->compute_pipeline_create(gi.shader.version_get_shader(gi.shader_version, i)); + { + String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + Vector<String> debug_modes; + debug_modes.push_back(""); + sdfgi_shader.debug.initialize(debug_modes, defines); + sdfgi_shader.debug_shader = sdfgi_shader.debug.version_create(); + sdfgi_shader.debug_shader_version = sdfgi_shader.debug.version_get_shader(sdfgi_shader.debug_shader, 0); + sdfgi_shader.debug_pipeline = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.debug_shader_version); } + { + String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; - gi.sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(GI::SDFGIData)); - } - { - String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; - Vector<String> debug_modes; - debug_modes.push_back(""); - sdfgi_shader.debug.initialize(debug_modes, defines); - sdfgi_shader.debug_shader = sdfgi_shader.debug.version_create(); - sdfgi_shader.debug_shader_version = sdfgi_shader.debug.version_get_shader(sdfgi_shader.debug_shader, 0); - sdfgi_shader.debug_pipeline = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.debug_shader_version); - } - { - String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; - - Vector<String> versions; - versions.push_back("\n#define MODE_PROBES\n"); - versions.push_back("\n#define MODE_VISIBILITY\n"); + Vector<String> versions; + versions.push_back("\n#define MODE_PROBES\n"); + versions.push_back("\n#define MODE_VISIBILITY\n"); - sdfgi_shader.debug_probes.initialize(versions, defines); - sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create(); + sdfgi_shader.debug_probes.initialize(versions, defines); + sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create(); - { - RD::PipelineRasterizationState rs; - rs.cull_mode = RD::POLYGON_CULL_DISABLED; - RD::PipelineDepthStencilState ds; - ds.enable_depth_test = true; - ds.enable_depth_write = true; - ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; - for (int i = 0; i < SDGIShader::PROBE_DEBUG_MAX; i++) { - RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i); - sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + { + RD::PipelineRasterizationState rs; + rs.cull_mode = RD::POLYGON_CULL_DISABLED; + RD::PipelineDepthStencilState ds; + ds.enable_depth_test = true; + ds.enable_depth_write = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; + for (int i = 0; i < SDGIShader::PROBE_DEBUG_MAX; i++) { + RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i); + sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + } } } + default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES); } //cluster setup @@ -8303,7 +8519,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { cluster.lights_instances = memnew_arr(RID, cluster.max_lights); cluster.lights_shadow_rect_cache = memnew_arr(Rect2i, cluster.max_lights); - cluster.max_directional_lights = 8; + cluster.max_directional_lights = MAX_DIRECTIONAL_LIGHTS; uint32_t directional_light_buffer_size = cluster.max_directional_lights * sizeof(Cluster::DirectionalLightData); cluster.directional_lights = memnew_arr(Cluster::DirectionalLightData, cluster.max_directional_lights); cluster.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); @@ -8318,7 +8534,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { cluster.builder.setup(16, 8, 24); - { + if (!low_end) { String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n"; Vector<String> volumetric_fog_modes; volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); @@ -8331,7 +8547,6 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { volumetric_fog.pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, i)); } } - default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES); { RD::SamplerState sampler; @@ -8344,7 +8559,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_shape")))); camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter")); - environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); + environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size"), GLOBAL_GET("rendering/quality/ssao/adaptive_target"), GLOBAL_GET("rendering/quality/ssao/blur_passes"), GLOBAL_GET("rendering/quality/ssao/fadeout_from"), GLOBAL_GET("rendering/quality/ssao/fadeout_to")); screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled"); screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"); screen_space_roughness_limiter_limit = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit"); @@ -8365,9 +8580,11 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/volumetric_fog/use_filter")); environment_set_volumetric_fog_directional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/directional_shadow_shrink")); environment_set_volumetric_fog_positional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/positional_shadow_shrink")); + + cull_argument.set_page_pool(&cull_argument_pool); } -RasterizerSceneRD::~RasterizerSceneRD() { +RendererSceneRenderRD::~RendererSceneRenderRD() { for (Map<Vector2i, ShadowMap>::Element *E = shadow_maps.front(); E; E = E->next()) { RD::get_singleton()->free(E->get().depth); } @@ -8379,23 +8596,26 @@ RasterizerSceneRD::~RasterizerSceneRD() { RD::get_singleton()->free(sky_scene_state.uniform_set); } - RD::get_singleton()->free(default_giprobe_buffer); - RD::get_singleton()->free(gi_probe_lights_uniform); - RD::get_singleton()->free(gi.sdfgi_ubo); + if (!low_end) { + RD::get_singleton()->free(default_giprobe_buffer); + RD::get_singleton()->free(gi_probe_lights_uniform); + RD::get_singleton()->free(gi.sdfgi_ubo); + + giprobe_debug_shader.version_free(giprobe_debug_shader_version); + giprobe_shader.version_free(giprobe_lighting_shader_version); + gi.shader.version_free(gi.shader_version); + sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader); + sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader); + sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader); + sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader); + sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader); - giprobe_debug_shader.version_free(giprobe_debug_shader_version); - giprobe_shader.version_free(giprobe_lighting_shader_version); - gi.shader.version_free(gi.shader_version); - sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader); - sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader); - sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader); - sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader); - sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader); + volumetric_fog.shader.version_free(volumetric_fog.shader_version); - volumetric_fog.shader.version_free(volumetric_fog.shader_version); + memdelete_arr(gi_probe_lights); + } - memdelete_arr(gi_probe_lights); - SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY); + SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY); sky_shader.shader.version_free(md->shader_data->version); RD::get_singleton()->free(sky_scene_state.directional_light_buffer); RD::get_singleton()->free(sky_scene_state.uniform_buffer); @@ -8426,4 +8646,5 @@ RasterizerSceneRD::~RasterizerSceneRD() { RD::get_singleton()->free(shadow_sampler); directional_shadow_atlas_set_size(0); + cull_argument.reset(); //avoid exit error } diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 3d5310bb7e..3f9c117602 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_scene_rd.h */ +/* renderer_scene_render_rd.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,27 +28,28 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_SCENE_RD_H -#define RASTERIZER_SCENE_RD_H +#ifndef RENDERING_SERVER_SCENE_RENDER_RD_H +#define RENDERING_SERVER_SCENE_RENDER_RD_H #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" -#include "servers/rendering/rasterizer.h" -#include "servers/rendering/rasterizer_rd/light_cluster_builder.h" -#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" -#include "servers/rendering/rasterizer_rd/shaders/gi.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/giprobe.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/sky.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/volumetric_fog.glsl.gen.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_rd/light_cluster_builder.h" +#include "servers/rendering/renderer_rd/renderer_storage_rd.h" +#include "servers/rendering/renderer_rd/shaders/gi.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/giprobe.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/giprobe_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" -class RasterizerSceneRD : public RasterizerScene { +class RendererSceneRenderRD : public RendererSceneRender { protected: double time; @@ -103,17 +104,17 @@ protected: }; virtual RenderBufferData *_create_render_buffer_data() = 0; - void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count); - void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform); - void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment); - void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, uint32_t &r_gi_probes_used); + void _setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count); + void _setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform); + void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment); + void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used); - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0; - virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake) = 0; - virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; - virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; - virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, InstanceBase **p_cull_result, int p_cull_count) = 0; + virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0; + virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0; + virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0; virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform); @@ -133,16 +134,19 @@ protected: void _setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size); void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform); void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform); - void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count); + void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes); + // needed for a single argument calls (material and uv2) + PagedArrayPool<GeometryInstance *> cull_argument_pool; + PagedArray<GeometryInstance *> cull_argument; //need this to exist private: RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; double time_step = 0; - static RasterizerSceneRD *singleton; + static RendererSceneRenderRD *singleton; int roughness_layers; - RasterizerStorageRD *storage; + RendererStorageRD *storage; struct ReflectionData { struct Layer { @@ -200,11 +204,11 @@ private: RID default_shader_rd; } sky_shader; - struct SkyShaderData : public RasterizerStorageRD::ShaderData { + struct SkyShaderData : public RendererStorageRD::ShaderData { bool valid; RID version; - RenderPipelineVertexFormatCacheRD pipelines[SKY_VERSION_MAX]; + PipelineCacheRD pipelines[SKY_VERSION_MAX]; Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms; @@ -224,21 +228,22 @@ private: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererStorage::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(); }; - RasterizerStorageRD::ShaderData *_create_sky_shader_func(); - static RasterizerStorageRD::ShaderData *_create_sky_shader_funcs() { - return static_cast<RasterizerSceneRD *>(singleton)->_create_sky_shader_func(); + RendererStorageRD::ShaderData *_create_sky_shader_func(); + static RendererStorageRD::ShaderData *_create_sky_shader_funcs() { + return static_cast<RendererSceneRenderRD *>(singleton)->_create_sky_shader_func(); }; - struct SkyMaterialData : public RasterizerStorageRD::MaterialData { + struct SkyMaterialData : public RendererStorageRD::MaterialData { uint64_t last_frame; SkyShaderData *shader_data; RID uniform_buffer; @@ -253,9 +258,9 @@ private: virtual ~SkyMaterialData(); }; - RasterizerStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); - static RasterizerStorageRD::MaterialData *_create_sky_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { - return static_cast<RasterizerSceneRD *>(singleton)->_create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); + RendererStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); + static RendererStorageRD::MaterialData *_create_sky_material_funcs(RendererStorageRD::ShaderData *p_shader) { + return static_cast<RendererSceneRenderRD *>(singleton)->_create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); }; enum SkyTextureSetVersion { @@ -338,7 +343,7 @@ private: Vector<Reflection> reflections; }; - RID_Owner<ReflectionAtlas> reflection_atlas_owner; + mutable RID_Owner<ReflectionAtlas> reflection_atlas_owner; /* REFLECTION PROBE INSTANCE */ @@ -370,6 +375,15 @@ private: mutable RID_Owner<DecalInstance> decal_instance_owner; + /* LIGHTMAP INSTANCE */ + + struct LightmapInstance { + RID lightmap; + Transform transform; + }; + + mutable RID_Owner<LightmapInstance> lightmap_instance_owner; + /* GIPROBE INSTANCE */ struct GIProbeLight { @@ -512,7 +526,7 @@ private: GiprobeDebugShaderRD giprobe_debug_shader; RID giprobe_debug_shader_version; RID giprobe_debug_shader_version_shaders[GI_PROBE_DEBUG_MAX]; - RenderPipelineVertexFormatCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX]; + PipelineCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX]; RID giprobe_debug_uniform_set; /* SHADOW ATLAS */ @@ -736,13 +750,14 @@ private: /// SSAO bool ssao_enabled = false; - float ssao_radius = 1; - float ssao_intensity = 1; - float ssao_bias = 0.01; + float ssao_radius = 1.0; + float ssao_intensity = 2.0; + float ssao_power = 1.5; + float ssao_detail = 0.5; + float ssao_horizon = 0.06; + float ssao_sharpness = 0.98; float ssao_direct_light_affect = 0.0; float ssao_ao_channel_affect = 0.0; - float ssao_blur_edge_sharpness = 4.0; - RS::EnvironmentSSAOBlur ssao_blur = RS::ENV_SSAO_BLUR_3x3; /// SSR /// @@ -763,10 +778,25 @@ private: float sdfgi_normal_bias = 1.1; float sdfgi_probe_bias = 1.1; RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_DISABLED; + + /// Adjustments + + bool adjustments_enabled = false; + float adjustments_brightness = 1.0f; + float adjustments_contrast = 1.0f; + float adjustments_saturation = 1.0f; + bool use_1d_color_correction = false; + RID color_correction = RID(); }; RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; bool ssao_half_size = false; + bool ssao_using_half_size = false; + float ssao_adaptive_target = 0.5; + int ssao_blur_passes = 2; + float ssao_fadeout_from = 50.0; + float ssao_fadeout_to = 300.0; + bool glow_bicubic_upscale = false; bool glow_high_quality = false; RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGNESS_QUALITY_LOW; @@ -851,8 +881,12 @@ private: struct SSAO { RID depth; Vector<RID> depth_slices; - RID ao[2]; - RID ao_full; //when using half-size + RID ao_deinterleaved; + Vector<RID> ao_deinterleaved_slices; + RID ao_pong; + Vector<RID> ao_pong_slices; + RID ao_final; + RID importance_map[2]; } ssao; struct SSR { @@ -1068,7 +1102,7 @@ private: RID debug_probes_shader; RID debug_probes_shader_version; - RenderPipelineVertexFormatCacheRD debug_probes_pipeline[PROBE_DEBUG_MAX]; + PipelineCacheRD debug_probes_pipeline[PROBE_DEBUG_MAX]; struct Light { float color[3]; @@ -1446,7 +1480,12 @@ private: float weight; }; + bool low_end = false; + public: + virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance) = 0; + virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0; + /* SHADOW ATLAS API */ RID shadow_atlas_create(); @@ -1490,7 +1529,7 @@ public: virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const; virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const; virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const; - virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count); + virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const Vector<RID> &p_directional_lights, const RID *p_positional_light_instances, uint32_t p_positional_light_count); RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; } /* SKY API */ @@ -1555,8 +1594,8 @@ public: virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size); void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance); - void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); - void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size); + void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect); + 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); bool environment_is_ssao_enabled(RID p_env) const; float environment_get_ssao_ao_affect(RID p_env) const; float environment_get_ssao_light_affect(RID p_env) const; @@ -1571,7 +1610,7 @@ public: RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const; void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {} + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction); virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size); @@ -1716,6 +1755,8 @@ public: virtual RID reflection_atlas_create(); virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count); + virtual int reflection_atlas_get_size(RID p_ref_atlas) const; + _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) { ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas); ERR_FAIL_COND_V(!atlas, RID()); @@ -1794,10 +1835,25 @@ public: return decal->transform; } + virtual RID lightmap_instance_create(RID p_lightmap); + virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform); + _FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) { + return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr; + } + + _FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) { + LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance); + return li->lightmap; + } + _FORCE_INLINE_ Transform lightmap_instance_get_transform(RID p_lightmap_instance) { + LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance); + return li->transform; + } + RID gi_probe_instance_create(RID p_base); void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform); bool gi_probe_needs_update(RID p_probe) const; - void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects); + void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects); void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; } @@ -1872,16 +1928,16 @@ public: float render_buffers_get_volumetric_fog_end(RID p_render_buffers); float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers); - void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold); - void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count); + void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0); - void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); + void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region); - void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count); - void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count); + void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances); + void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result); - void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, InstanceBase **p_cull_result, int p_cull_count); + void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances); virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; @@ -1942,8 +1998,10 @@ public: void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir); - RasterizerSceneRD(RasterizerStorageRD *p_storage); - ~RasterizerSceneRD(); + bool is_low_end() const; + + RendererSceneRenderRD(RendererStorageRD *p_storage); + ~RendererSceneRenderRD(); }; #endif // RASTERIZER_SCENE_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 444ef9c49a..b74a1083e7 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_storage_rd.cpp */ +/* renderer_storage_rd.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rasterizer_storage_rd.h" +#include "renderer_storage_rd.h" #include "core/config/engine.h" #include "core/config/project_settings.h" #include "core/io/resource_loader.h" -#include "rasterizer_rd.h" +#include "renderer_compositor_rd.h" #include "servers/rendering/shader_language.h" -Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { +Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) { Ref<Image> image = p_image->duplicate(); switch (p_image->get_format()) { @@ -318,7 +318,7 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; } break; //unsigned float bc6hu - case Image::FORMAT_PVRTC2: { + case Image::FORMAT_PVRTC1_2: { //this is not properly supported by MoltekVK it seems, so best to use ETC2 if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; @@ -336,7 +336,7 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; } break; //pvrtc - case Image::FORMAT_PVRTC2A: { + case Image::FORMAT_PVRTC1_2A: { //this is not properly supported by MoltekVK it seems, so best to use ETC2 if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; @@ -353,7 +353,7 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; } break; - case Image::FORMAT_PVRTC4: { + case Image::FORMAT_PVRTC1_4: { //this is not properly supported by MoltekVK it seems, so best to use ETC2 if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; @@ -370,7 +370,7 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; } break; - case Image::FORMAT_PVRTC4A: { + case Image::FORMAT_PVRTC1_4A: { //this is not properly supported by MoltekVK it seems, so best to use ETC2 if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; @@ -535,9 +535,9 @@ Ref<Image> RasterizerStorageRD::_validate_texture_format(const Ref<Image> &p_ima return image; } -RID RasterizerStorageRD::texture_2d_create(const Ref<Image> &p_image) { +RID RendererStorageRD::texture_2d_create(const Ref<Image> &p_image) { ERR_FAIL_COND_V(p_image.is_null(), RID()); - ERR_FAIL_COND_V(p_image->empty(), RID()); + ERR_FAIL_COND_V(p_image->is_empty(), RID()); TextureToRDFormat ret_format; Ref<Image> image = _validate_texture_format(p_image, ret_format); @@ -567,7 +567,7 @@ RID RasterizerStorageRD::texture_2d_create(const Ref<Image> &p_image) { rd_format.depth = 1; rd_format.array_layers = 1; rd_format.mipmaps = texture.mipmaps; - rd_format.type = texture.rd_type; + rd_format.texture_type = texture.rd_type; rd_format.samples = RD::TEXTURE_SAMPLES_1; rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { @@ -605,7 +605,7 @@ RID RasterizerStorageRD::texture_2d_create(const Ref<Image> &p_image) { return texture_owner.make_rid(texture); } -RID RasterizerStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { +RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { ERR_FAIL_COND_V(p_layers.size() == 0, RID()); ERR_FAIL_COND_V(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6, RID()); @@ -620,7 +620,7 @@ RID RasterizerStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_l Image::Format valid_format = Image::FORMAT_MAX; for (int i = 0; i < p_layers.size(); i++) { - ERR_FAIL_COND_V(p_layers[i]->empty(), RID()); + ERR_FAIL_COND_V(p_layers[i]->is_empty(), RID()); if (i == 0) { valid_width = p_layers[i]->get_width(); @@ -675,7 +675,7 @@ RID RasterizerStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_l rd_format.depth = 1; rd_format.array_layers = texture.layers; rd_format.mipmaps = texture.mipmaps; - rd_format.type = texture.rd_type; + rd_format.texture_type = texture.rd_type; rd_format.samples = RD::TEXTURE_SAMPLES_1; rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { @@ -715,7 +715,7 @@ RID RasterizerStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_l return texture_owner.make_rid(texture); } -RID RasterizerStorageRD::texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { +RID RendererStorageRD::texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { ERR_FAIL_COND_V(p_data.size() == 0, RID()); Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); if (verr != Image::VALIDATE_3D_OK) { @@ -793,7 +793,7 @@ RID RasterizerStorageRD::texture_3d_create(Image::Format p_format, int p_width, rd_format.depth = texture.depth; rd_format.array_layers = 1; rd_format.mipmaps = texture.mipmaps; - rd_format.type = texture.rd_type; + rd_format.texture_type = texture.rd_type; rd_format.samples = RD::TEXTURE_SAMPLES_1; rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { @@ -831,7 +831,7 @@ RID RasterizerStorageRD::texture_3d_create(Image::Format p_format, int p_width, return texture_owner.make_rid(texture); } -RID RasterizerStorageRD::texture_proxy_create(RID p_base) { +RID RendererStorageRD::texture_proxy_create(RID p_base) { Texture *tex = texture_owner.getornull(p_base); ERR_FAIL_COND_V(!tex, RID()); Texture proxy_tex = *tex; @@ -854,8 +854,8 @@ RID RasterizerStorageRD::texture_proxy_create(RID p_base) { return rid; } -void RasterizerStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) { - ERR_FAIL_COND(p_image.is_null() || p_image->empty()); +void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) { + ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); @@ -876,15 +876,15 @@ void RasterizerStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_ RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data(), !p_immediate); } -void RasterizerStorageRD::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) { +void RendererStorageRD::texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer) { _texture_2d_update(p_texture, p_image, p_layer, true); } -void RasterizerStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { +void RendererStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) { _texture_2d_update(p_texture, p_image, p_layer, false); } -void RasterizerStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { +void RendererStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); ERR_FAIL_COND(tex->type != Texture::TYPE_3D); @@ -921,7 +921,7 @@ void RasterizerStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Imag RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data, true); } -void RasterizerStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { +void RendererStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); ERR_FAIL_COND(!tex->is_proxy); @@ -961,7 +961,7 @@ void RasterizerStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { } //these two APIs can be used together or in combination with the others. -RID RasterizerStorageRD::texture_2d_placeholder_create() { +RID RendererStorageRD::texture_2d_placeholder_create() { //this could be better optimized to reuse an existing image , done this way //for now to get it working Ref<Image> image; @@ -977,7 +977,7 @@ RID RasterizerStorageRD::texture_2d_placeholder_create() { return texture_2d_create(image); } -RID RasterizerStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayeredType p_layered_type) { +RID RendererStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayeredType p_layered_type) { //this could be better optimized to reuse an existing image , done this way //for now to get it working Ref<Image> image; @@ -1003,7 +1003,7 @@ RID RasterizerStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayere return texture_2d_layered_create(images, p_layered_type); } -RID RasterizerStorageRD::texture_3d_placeholder_create() { +RID RendererStorageRD::texture_3d_placeholder_create() { //this could be better optimized to reuse an existing image , done this way //for now to get it working Ref<Image> image; @@ -1025,7 +1025,7 @@ RID RasterizerStorageRD::texture_3d_placeholder_create() { return texture_3d_create(Image::FORMAT_RGBA8, 4, 4, 4, false, images); } -Ref<Image> RasterizerStorageRD::texture_2d_get(RID p_texture) const { +Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND_V(!tex, Ref<Image>()); @@ -1039,7 +1039,7 @@ Ref<Image> RasterizerStorageRD::texture_2d_get(RID p_texture) const { Ref<Image> image; image.instance(); image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->empty(), Ref<Image>()); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); if (tex->format != tex->validated_format) { image->convert(tex->format); } @@ -1053,7 +1053,7 @@ Ref<Image> RasterizerStorageRD::texture_2d_get(RID p_texture) const { return image; } -Ref<Image> RasterizerStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const { +Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND_V(!tex, Ref<Image>()); @@ -1062,7 +1062,7 @@ Ref<Image> RasterizerStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) Ref<Image> image; image.instance(); image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->empty(), Ref<Image>()); + ERR_FAIL_COND_V(image->is_empty(), Ref<Image>()); if (tex->format != tex->validated_format) { image->convert(tex->format); } @@ -1070,7 +1070,7 @@ Ref<Image> RasterizerStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) return image; } -Vector<Ref<Image>> RasterizerStorageRD::texture_3d_get(RID p_texture) const { +Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); @@ -1090,7 +1090,7 @@ Vector<Ref<Image>> RasterizerStorageRD::texture_3d_get(RID p_texture) const { Ref<Image> img; img.instance(); img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); - ERR_FAIL_COND_V(img->empty(), Vector<Ref<Image>>()); + ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>()); if (tex->format != tex->validated_format) { img->convert(tex->format); } @@ -1101,7 +1101,7 @@ Vector<Ref<Image>> RasterizerStorageRD::texture_3d_get(RID p_texture) const { return ret; } -void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) { +void RendererStorageRD::texture_replace(RID p_texture, RID p_by_texture) { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); ERR_FAIL_COND(tex->proxy_to.is_valid()); //can't replace proxy @@ -1150,7 +1150,7 @@ void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) { } } -void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) { +void RendererStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); ERR_FAIL_COND(tex->type != Texture::TYPE_2D); @@ -1158,53 +1158,53 @@ void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, tex->height_2d = p_height; } -void RasterizerStorageRD::texture_set_path(RID p_texture, const String &p_path) { +void RendererStorageRD::texture_set_path(RID p_texture, const String &p_path) { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); tex->path = p_path; } -String RasterizerStorageRD::texture_get_path(RID p_texture) const { +String RendererStorageRD::texture_get_path(RID p_texture) const { return String(); } -void RasterizerStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { +void RendererStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); tex->detect_3d_callback_ud = p_userdata; tex->detect_3d_callback = p_callback; } -void RasterizerStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { +void RendererStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); tex->detect_normal_callback_ud = p_userdata; tex->detect_normal_callback = p_callback; } -void RasterizerStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { +void RendererStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { Texture *tex = texture_owner.getornull(p_texture); ERR_FAIL_COND(!tex); tex->detect_roughness_callback_ud = p_userdata; tex->detect_roughness_callback = p_callback; } -void RasterizerStorageRD::texture_debug_usage(List<RS::TextureInfo> *r_info) { +void RendererStorageRD::texture_debug_usage(List<RS::TextureInfo> *r_info) { } -void RasterizerStorageRD::texture_set_proxy(RID p_proxy, RID p_base) { +void RendererStorageRD::texture_set_proxy(RID p_proxy, RID p_base) { } -void RasterizerStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { +void RendererStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { } -Size2 RasterizerStorageRD::texture_size_with_proxy(RID p_proxy) { +Size2 RendererStorageRD::texture_size_with_proxy(RID p_proxy) { return texture_2d_get_size(p_proxy); } /* CANVAS TEXTURE */ -void RasterizerStorageRD::CanvasTexture::clear_sets() { +void RendererStorageRD::CanvasTexture::clear_sets() { if (cleared_cache) { return; } @@ -1219,22 +1219,22 @@ void RasterizerStorageRD::CanvasTexture::clear_sets() { cleared_cache = true; } -RasterizerStorageRD::CanvasTexture::~CanvasTexture() { +RendererStorageRD::CanvasTexture::~CanvasTexture() { clear_sets(); } -RID RasterizerStorageRD::canvas_texture_create() { +RID RendererStorageRD::canvas_texture_create() { return canvas_texture_owner.make_rid(memnew(CanvasTexture)); } -void RasterizerStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { +void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture); switch (p_channel) { case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { ct->diffuse = p_texture; } break; case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { - ct->normalmap = p_texture; + ct->normal_map = p_texture; } break; case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { ct->specular = p_texture; @@ -1244,7 +1244,7 @@ void RasterizerStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::C ct->clear_sets(); } -void RasterizerStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { +void RendererStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture); ct->specular_color.r = p_specular_color.r; ct->specular_color.g = p_specular_color.g; @@ -1253,19 +1253,19 @@ void RasterizerStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_tex ct->clear_sets(); } -void RasterizerStorageRD::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { +void RendererStorageRD::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture); ct->texture_filter = p_filter; ct->clear_sets(); } -void RasterizerStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { +void RendererStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture); ct->texture_repeat = p_repeat; ct->clear_sets(); } -bool RasterizerStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { +bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { CanvasTexture *ct = nullptr; Texture *t = texture_owner.getornull(p_texture); @@ -1298,7 +1298,7 @@ bool RasterizerStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canv Vector<RD::Uniform> uniforms; { //diffuse RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; t = texture_owner.getornull(ct->diffuse); @@ -1313,10 +1313,10 @@ bool RasterizerStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canv } { //normal RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - t = texture_owner.getornull(ct->normalmap); + t = texture_owner.getornull(ct->normal_map); if (!t) { u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); ct->use_normal_cache = false; @@ -1328,7 +1328,7 @@ bool RasterizerStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canv } { //specular RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; t = texture_owner.getornull(ct->specular); @@ -1343,7 +1343,7 @@ bool RasterizerStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canv } { //sampler RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 3; u.ids.push_back(sampler_rd_get_default(filter, repeat)); uniforms.push_back(u); @@ -1365,7 +1365,7 @@ bool RasterizerStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canv /* SHADER API */ -RID RasterizerStorageRD::shader_create() { +RID RendererStorageRD::shader_create() { Shader shader; shader.data = nullptr; shader.type = SHADER_TYPE_MAX; @@ -1373,7 +1373,7 @@ RID RasterizerStorageRD::shader_create() { return shader_owner.make_rid(shader); } -void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) { +void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) { Shader *shader = shader_owner.getornull(p_shader); ERR_FAIL_COND(!shader); @@ -1438,18 +1438,18 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) { for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); - material->instance_dependency.instance_notify_changed(false, true); + material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); _material_queue_update(material, true, true); } } -String RasterizerStorageRD::shader_get_code(RID p_shader) const { +String RendererStorageRD::shader_get_code(RID p_shader) const { Shader *shader = shader_owner.getornull(p_shader); ERR_FAIL_COND_V(!shader, String()); return shader->code; } -void RasterizerStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { +void RendererStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { Shader *shader = shader_owner.getornull(p_shader); ERR_FAIL_COND(!shader); if (shader->data) { @@ -1457,7 +1457,7 @@ void RasterizerStorageRD::shader_get_param_list(RID p_shader, List<PropertyInfo> } } -void RasterizerStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { +void RendererStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { Shader *shader = shader_owner.getornull(p_shader); ERR_FAIL_COND(!shader); @@ -1475,7 +1475,7 @@ void RasterizerStorageRD::shader_set_default_texture_param(RID p_shader, const S } } -RID RasterizerStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { +RID RendererStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { Shader *shader = shader_owner.getornull(p_shader); ERR_FAIL_COND_V(!shader, RID()); if (shader->default_texture_parameter.has(p_name)) { @@ -1485,7 +1485,7 @@ RID RasterizerStorageRD::shader_get_default_texture_param(RID p_shader, const St return RID(); } -Variant RasterizerStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const { +Variant RendererStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const { Shader *shader = shader_owner.getornull(p_shader); ERR_FAIL_COND_V(!shader, Variant()); if (shader->data) { @@ -1494,14 +1494,23 @@ Variant RasterizerStorageRD::shader_get_param_default(RID p_shader, const String return Variant(); } -void RasterizerStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) { +void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) { ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); shader_data_request_func[p_shader_type] = p_function; } +RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const { + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode()); + if (shader->data) { + return shader->data->get_native_source_code(); + } + return RS::ShaderNativeSourceCode(); +} + /* COMMON MATERIAL API */ -RID RasterizerStorageRD::material_create() { +RID RendererStorageRD::material_create() { Material material; material.data = nullptr; material.shader = nullptr; @@ -1519,7 +1528,7 @@ RID RasterizerStorageRD::material_create() { return id; } -void RasterizerStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { +void RendererStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { if (material->update_requested) { return; } @@ -1531,7 +1540,7 @@ void RasterizerStorageRD::_material_queue_update(Material *material, bool p_unif material->texture_dirty = material->texture_dirty || p_texture; } -void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) { +void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); @@ -1547,7 +1556,8 @@ void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) { } if (p_shader.is_null()) { - material->instance_dependency.instance_notify_changed(false, true); + material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); + material->shader_id = 0; return; } @@ -1555,6 +1565,7 @@ void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) { ERR_FAIL_COND(!shader); material->shader = shader; material->shader_type = shader->type; + material->shader_id = p_shader.get_local_index(); shader->owners.insert(material); if (shader->type == SHADER_TYPE_MAX) { @@ -1568,11 +1579,11 @@ void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) { material->data->set_next_pass(material->next_pass); material->data->set_render_priority(material->priority); //updating happens later - material->instance_dependency.instance_notify_changed(false, true); + material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); _material_queue_update(material, true, true); } -void RasterizerStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { +void RendererStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); @@ -1590,7 +1601,7 @@ void RasterizerStorageRD::material_set_param(RID p_material, const StringName &p } } -Variant RasterizerStorageRD::material_get_param(RID p_material, const StringName &p_param) const { +Variant RendererStorageRD::material_get_param(RID p_material, const StringName &p_param) const { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND_V(!material, Variant()); if (material->params.has(p_param)) { @@ -1600,7 +1611,7 @@ Variant RasterizerStorageRD::material_get_param(RID p_material, const StringName } } -void RasterizerStorageRD::material_set_next_pass(RID p_material, RID p_next_material) { +void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_material) { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); @@ -1613,10 +1624,10 @@ void RasterizerStorageRD::material_set_next_pass(RID p_material, RID p_next_mate material->data->set_next_pass(p_next_material); } - material->instance_dependency.instance_notify_changed(false, true); + material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); } -void RasterizerStorageRD::material_set_render_priority(RID p_material, int priority) { +void RendererStorageRD::material_set_render_priority(RID p_material, int priority) { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); material->priority = priority; @@ -1625,7 +1636,7 @@ void RasterizerStorageRD::material_set_render_priority(RID p_material, int prior } } -bool RasterizerStorageRD::material_is_animated(RID p_material) { +bool RendererStorageRD::material_is_animated(RID p_material) { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND_V(!material, false); if (material->shader && material->shader->data) { @@ -1638,7 +1649,7 @@ bool RasterizerStorageRD::material_is_animated(RID p_material) { return false; //by default nothing is animated } -bool RasterizerStorageRD::material_casts_shadows(RID p_material) { +bool RendererStorageRD::material_casts_shadows(RID p_material) { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND_V(!material, true); if (material->shader && material->shader->data) { @@ -1651,7 +1662,7 @@ bool RasterizerStorageRD::material_casts_shadows(RID p_material) { return true; //by default everything casts shadows } -void RasterizerStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { +void RendererStorageRD::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); if (material->shader && material->shader->data) { @@ -1663,16 +1674,16 @@ void RasterizerStorageRD::material_get_instance_shader_parameters(RID p_material } } -void RasterizerStorageRD::material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) { +void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) { Material *material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); - p_instance->update_dependency(&material->instance_dependency); + p_instance->update_dependency(&material->dependency); if (material->next_pass.is_valid()) { material_update_dependency(material->next_pass, p_instance); } } -void RasterizerStorageRD::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { +void RendererStorageRD::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); material_data_request_func[p_shader_type] = p_function; } @@ -2119,7 +2130,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, } } -void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { +void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { bool uses_global_buffer = false; for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = p_uniforms.front(); E; E = E->next()) { @@ -2133,7 +2144,7 @@ void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringNa if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { //this is a global variable, get the index to it - RasterizerStorageRD *rs = base_singleton; + RendererStorageRD *rs = base_singleton; GlobalVariables::Variable *gv = rs->global_variables.variables.getptr(E->key()); uint32_t index = 0; @@ -2180,7 +2191,7 @@ void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringNa } if (uses_global_buffer != (global_buffer_E != nullptr)) { - RasterizerStorageRD *rs = base_singleton; + RendererStorageRD *rs = base_singleton; if (uses_global_buffer) { global_buffer_E = rs->global_variables.materials_using_buffer.push_back(self); } else { @@ -2190,16 +2201,16 @@ void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map<StringNa } } -RasterizerStorageRD::MaterialData::~MaterialData() { +RendererStorageRD::MaterialData::~MaterialData() { if (global_buffer_E) { //unregister global buffers - RasterizerStorageRD *rs = base_singleton; + RendererStorageRD *rs = base_singleton; rs->global_variables.materials_using_buffer.erase(global_buffer_E); } if (global_texture_E) { //unregister global textures - RasterizerStorageRD *rs = base_singleton; + RendererStorageRD *rs = base_singleton; for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { GlobalVariables::Variable *v = rs->global_variables.variables.getptr(E->key()); @@ -2212,11 +2223,11 @@ RasterizerStorageRD::MaterialData::~MaterialData() { } } -void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { - RasterizerStorageRD *singleton = (RasterizerStorageRD *)RasterizerStorage::base_singleton; +void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, RID> &p_default_textures, const Vector<ShaderCompilerRD::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { + RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton; #ifdef TOOLS_ENABLED Texture *roughness_detect_texture = nullptr; - RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGNHESS_R; + RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R; Texture *normal_detect_texture = nullptr; #endif @@ -2229,7 +2240,7 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va RID texture; if (p_texture_uniforms[i].global) { - RasterizerStorageRD *rs = base_singleton; + RendererStorageRD *rs = base_singleton; uses_global_textures = true; @@ -2330,7 +2341,7 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va { //for textures no longer used, unregister them List<Map<StringName, uint64_t>::Element *> to_delete; - RasterizerStorageRD *rs = base_singleton; + RendererStorageRD *rs = base_singleton; for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { if (E->get() != global_textures_pass) { @@ -2359,7 +2370,7 @@ void RasterizerStorageRD::MaterialData::update_textures(const Map<StringName, Va } } -void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) { +void RendererStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) { Material *material = material_owner.getornull(p_material); if (material->shader_type != p_shader_type) { return; @@ -2369,7 +2380,7 @@ void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderT } } -void RasterizerStorageRD::_update_queued_materials() { +void RendererStorageRD::_update_queued_materials() { Material *material = material_update_list; while (material) { Material *next = material->update_next; @@ -2388,23 +2399,32 @@ void RasterizerStorageRD::_update_queued_materials() { /* MESH API */ -RID RasterizerStorageRD::mesh_create() { +RID RendererStorageRD::mesh_create() { return mesh_owner.make_rid(Mesh()); } -/// Returns stride -void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) { +void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) { + ERR_FAIL_COND(p_blend_shape_count < 0); + Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); - //ensure blend shape consistency - ERR_FAIL_COND(mesh->blend_shape_count && p_surface.blend_shapes.size() != (int)mesh->blend_shape_count); - ERR_FAIL_COND(mesh->blend_shape_count && p_surface.bone_aabbs.size() != mesh->bone_aabbs.size()); + ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist + + mesh->blend_shape_count = p_blend_shape_count; +} + +/// Returns stride +void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); #ifdef DEBUG_ENABLED //do a validation, to catch errors first { uint32_t stride = 0; + uint32_t attrib_stride = 0; + uint32_t skin_stride = 0; for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { if ((p_surface.format & (1 << i))) { @@ -2418,59 +2438,59 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_ } break; case RS::ARRAY_NORMAL: { - if (p_surface.format & RS::ARRAY_COMPRESS_NORMAL) { - stride += sizeof(int8_t) * 4; - } else { - stride += sizeof(float) * 4; - } + stride += sizeof(int32_t); } break; case RS::ARRAY_TANGENT: { - if (p_surface.format & RS::ARRAY_COMPRESS_TANGENT) { - stride += sizeof(int8_t) * 4; - } else { - stride += sizeof(float) * 4; - } + stride += sizeof(int32_t); } break; case RS::ARRAY_COLOR: { - if (p_surface.format & RS::ARRAY_COMPRESS_COLOR) { - stride += sizeof(int8_t) * 4; - } else { - stride += sizeof(float) * 4; - } - + attrib_stride += sizeof(int16_t) * 4; } break; case RS::ARRAY_TEX_UV: { - if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV) { - stride += sizeof(int16_t) * 2; - } else { - stride += sizeof(float) * 2; - } + attrib_stride += sizeof(float) * 2; } break; case RS::ARRAY_TEX_UV2: { - if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV2) { - stride += sizeof(int16_t) * 2; - } else { - stride += sizeof(float) * 2; - } + attrib_stride += sizeof(float) * 2; } break; - case RS::ARRAY_BONES: { - //assumed weights too - - //unique format, internally 16 bits, exposed as single array for 32 - - stride += sizeof(int32_t) * 4; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + int idx = i - RS::ARRAY_CUSTOM0; + uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; + uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; + uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; + attrib_stride += fmtsize[fmt]; } break; + case RS::ARRAY_WEIGHTS: + case RS::ARRAY_BONES: { + //uses a separate array + bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS; + skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8); + } break; } } } int expected_size = stride * p_surface.vertex_count; - ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); + ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); + + int bs_expected_size = expected_size * mesh->blend_shape_count; + + ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")"); + + int expected_attrib_size = attrib_stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")"); + + if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) { + expected_size = skin_stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); + } } #endif @@ -2480,9 +2500,25 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_ s->format = p_surface.format; s->primitive = p_surface.primitive; - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data); + bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0); + + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); + s->vertex_buffer_size = p_surface.vertex_data.size(); + + if (p_surface.attribute_data.size()) { + s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data); + } + if (p_surface.skin_data.size()) { + s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage); + s->skin_buffer_size = p_surface.skin_data.size(); + } + s->vertex_count = p_surface.vertex_count; + if (p_surface.format & RS::ARRAY_FORMAT_BONES) { + mesh->has_bone_weights = true; + } + if (p_surface.index_count) { bool is_index_16 = p_surface.vertex_count <= 65536; @@ -2505,21 +2541,54 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_ s->aabb = p_surface.aabb; s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. - for (int i = 0; i < p_surface.blend_shapes.size(); i++) { - if (p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()) { - memdelete(s); - ERR_FAIL_COND(p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()); - } - RID vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.blend_shapes[i].size(), p_surface.blend_shapes[i]); - s->blend_shapes.push_back(vertex_buffer); + if (mesh->blend_shape_count > 0) { + s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data); } - mesh->blend_shape_count = p_surface.blend_shapes.size(); + if (use_as_storage) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(s->vertex_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (s->skin_buffer.is_valid()) { + u.ids.push_back(s->skin_buffer); + } else { + u.ids.push_back(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (s->blend_shape_buffer.is_valid()) { + u.ids.push_back(s->blend_shape_buffer); + } else { + u.ids.push_back(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + + s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE); + } if (mesh->surface_count == 0) { mesh->bone_aabbs = p_surface.bone_aabbs; mesh->aabb = p_surface.aabb; } else { + if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) { + // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone + // Each surface may affect different numbers of bones. + mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); + } for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); } @@ -2532,18 +2601,24 @@ void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_ mesh->surfaces[mesh->surface_count] = s; mesh->surface_count++; - mesh->instance_dependency.instance_notify_changed(true, true); + for (List<MeshInstance *>::Element *E = mesh->instances.front(); E; E = E->next()) { + //update instances + MeshInstance *mi = E->get(); + _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1); + } + + mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); mesh->material_cache.clear(); } -int RasterizerStorageRD::mesh_get_blend_shape_count(RID p_mesh) const { +int RendererStorageRD::mesh_get_blend_shape_count(RID p_mesh) const { const Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!mesh, -1); return mesh->blend_shape_count; } -void RasterizerStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { +void RendererStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); ERR_FAIL_INDEX((int)p_mode, 2); @@ -2551,13 +2626,13 @@ void RasterizerStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMo mesh->blend_shape_mode = p_mode; } -RS::BlendShapeMode RasterizerStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const { +RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); return mesh->blend_shape_mode; } -void RasterizerStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { +void RendererStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); @@ -2568,17 +2643,17 @@ void RasterizerStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r); } -void RasterizerStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { +void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); mesh->surfaces[p_surface]->material = p_material; - mesh->instance_dependency.instance_notify_changed(false, true); + mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); mesh->material_cache.clear(); } -RID RasterizerStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const { +RID RendererStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!mesh, RID()); ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID()); @@ -2586,7 +2661,7 @@ RID RasterizerStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) co return mesh->surfaces[p_surface]->material; } -RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const { +RS::SurfaceData RendererStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!mesh, RS::SurfaceData()); ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData()); @@ -2596,6 +2671,12 @@ RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface) RS::SurfaceData sd; sd.format = s.format; sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + if (s.attribute_buffer.is_valid()) { + sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer); + } + if (s.skin_buffer.is_valid()) { + sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer); + } sd.vertex_count = s.vertex_count; sd.index_count = s.index_count; sd.primitive = s.primitive; @@ -2613,33 +2694,32 @@ RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface) sd.bone_aabbs = s.bone_aabbs; - for (int i = 0; i < s.blend_shapes.size(); i++) { - Vector<uint8_t> bs = RD::get_singleton()->buffer_get_data(s.blend_shapes[i]); - sd.blend_shapes.push_back(bs); + if (s.blend_shape_buffer.is_valid()) { + sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer); } return sd; } -int RasterizerStorageRD::mesh_get_surface_count(RID p_mesh) const { +int RendererStorageRD::mesh_get_surface_count(RID p_mesh) const { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!mesh, 0); return mesh->surface_count; } -void RasterizerStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { +void RendererStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); mesh->custom_aabb = p_aabb; } -AABB RasterizerStorageRD::mesh_get_custom_aabb(RID p_mesh) const { +AABB RendererStorageRD::mesh_get_custom_aabb(RID p_mesh) const { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!mesh, AABB()); return mesh->custom_aabb; } -AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) { +AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!mesh, AABB()); @@ -2744,12 +2824,18 @@ AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) { return aabb; } -void RasterizerStorageRD::mesh_clear(RID p_mesh) { +void RendererStorageRD::mesh_clear(RID p_mesh) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); for (uint32_t i = 0; i < mesh->surface_count; i++) { Mesh::Surface &s = *mesh->surfaces[i]; RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions + if (s.attribute_buffer.is_valid()) { + RD::get_singleton()->free(s.attribute_buffer); + } + if (s.skin_buffer.is_valid()) { + RD::get_singleton()->free(s.skin_buffer); + } if (s.versions) { memfree(s.versions); //reallocs, so free with memfree. } @@ -2765,12 +2851,8 @@ void RasterizerStorageRD::mesh_clear(RID p_mesh) { memdelete_arr(s.lods); } - for (int32_t j = 0; j < s.blend_shapes.size(); j++) { - RD::get_singleton()->free(s.blend_shapes[j]); - } - - if (s.blend_shape_base_buffer.is_valid()) { - RD::get_singleton()->free(s.blend_shape_base_buffer); + if (s.blend_shape_buffer.is_valid()) { + RD::get_singleton()->free(s.blend_shape_buffer); } memdelete(mesh->surfaces[i]); @@ -2782,22 +2864,231 @@ void RasterizerStorageRD::mesh_clear(RID p_mesh) { mesh->surfaces = nullptr; mesh->surface_count = 0; mesh->material_cache.clear(); - mesh->instance_dependency.instance_notify_changed(true, true); + //clear instance data + for (List<MeshInstance *>::Element *E = mesh->instances.front(); E; E = E->next()) { + MeshInstance *mi = E->get(); + _mesh_instance_clear(mi); + } + mesh->has_bone_weights = false; + mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); +} + +bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, false); + + return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton); +} + +/* MESH INSTANCE */ + +RID RendererStorageRD::mesh_instance_create(RID p_base) { + Mesh *mesh = mesh_owner.getornull(p_base); + ERR_FAIL_COND_V(!mesh, RID()); + + MeshInstance *mi = memnew(MeshInstance); + + mi->mesh = mesh; + + for (uint32_t i = 0; i < mesh->surface_count; i++) { + _mesh_instance_add_surface(mi, mesh, i); + } + + mi->I = mesh->instances.push_back(mi); + + mi->dirty = true; + + return mesh_instance_owner.make_rid(mi); +} +void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) { + MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance); + if (mi->skeleton == p_skeleton) { + return; + } + mi->skeleton = p_skeleton; + mi->skeleton_version = 0; + mi->dirty = true; +} + +void RendererStorageRD::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) { + MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance); + ERR_FAIL_COND(!mi); + ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size()); + mi->blend_weights[p_shape] = p_weight; + mi->weights_dirty = true; + //will be eventually updated +} + +void RendererStorageRD::_mesh_instance_clear(MeshInstance *mi) { + for (uint32_t i = 0; i < mi->surfaces.size(); i++) { + if (mi->surfaces[i].vertex_buffer.is_valid()) { + RD::get_singleton()->free(mi->surfaces[i].vertex_buffer); + } + if (mi->surfaces[i].versions) { + for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { + RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array); + } + memfree(mi->surfaces[i].versions); + } + } + mi->surfaces.clear(); + + if (mi->blend_weights_buffer.is_valid()) { + RD::get_singleton()->free(mi->blend_weights_buffer); + } + mi->blend_weights.clear(); + mi->weights_dirty = false; + mi->skeleton_version = 0; +} + +void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) { + if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) { + mi->blend_weights.resize(mesh->blend_shape_count); + for (uint32_t i = 0; i < mi->blend_weights.size(); i++) { + mi->blend_weights[i] = 0; + } + mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array()); + mi->weights_dirty = true; + } + + MeshInstance::Surface s; + if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) { + //surface warrants transform + s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true); + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(s.vertex_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + if (mi->blend_weights_buffer.is_valid()) { + u.ids.push_back(mi->blend_weights_buffer); + } else { + u.ids.push_back(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE); + } + + mi->surfaces.push_back(s); + mi->dirty = true; +} + +void RendererStorageRD::mesh_instance_check_for_update(RID p_mesh_instance) { + MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance); + + bool needs_update = mi->dirty; + + if (mi->weights_dirty && !mi->weight_update_list.in_list()) { + dirty_mesh_instance_weights.add(&mi->weight_update_list); + needs_update = true; + } + + if (mi->array_update_list.in_list()) { + return; + } + + if (!needs_update && mi->skeleton.is_valid()) { + Skeleton *sk = skeleton_owner.getornull(mi->skeleton); + if (sk && sk->version != mi->skeleton_version) { + needs_update = true; + } + } + + if (needs_update) { + dirty_mesh_instance_arrays.add(&mi->array_update_list); + } } -void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface *s, uint32_t p_input_mask) { - uint32_t version = s->version_count; - s->version_count++; - s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); +void RendererStorageRD::update_mesh_instances() { + while (dirty_mesh_instance_weights.first()) { + MeshInstance *mi = dirty_mesh_instance_weights.first()->self(); - Mesh::Surface::Version &v = s->versions[version]; + if (mi->blend_weights_buffer.is_valid()) { + RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr(), true); + } + dirty_mesh_instance_weights.remove(&mi->weight_update_list); + mi->weights_dirty = false; + } + if (dirty_mesh_instance_arrays.first() == nullptr) { + return; //nothing to do + } + + //process skeletons and blend shapes + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + while (dirty_mesh_instance_arrays.first()) { + MeshInstance *mi = dirty_mesh_instance_arrays.first()->self(); + + Skeleton *sk = skeleton_owner.getornull(mi->skeleton); + + for (uint32_t i = 0; i < mi->surfaces.size(); i++) { + if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) { + continue; + } + + bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE); + if (sk && sk->uniform_set_mi.is_valid()) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON); + } + + SkeletonShader::PushConstant push_constant; + + push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL; + push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT; + push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES); + push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0; + push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count; + push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; + push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; + push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2; + + push_constant.blend_shape_count = mi->mesh->blend_shape_count; + push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED; + push_constant.pad0 = 0; + push_constant.pad1 = 0; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant)); + + //dispatch without barrier, so all is done at the same time + RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1, 64, 1, 1); + } + + mi->dirty = false; + if (sk) { + mi->skeleton_version = sk->version; + } + dirty_mesh_instance_arrays.remove(&mi->array_update_list); + } + + RD::get_singleton()->compute_list_end(); +} + +void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) { Vector<RD::VertexAttribute> attributes; Vector<RID> buffers; uint32_t stride = 0; + uint32_t attribute_stride = 0; + uint32_t skin_stride = 0; - for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { + for (int i = 0; i < RS::ARRAY_INDEX; i++) { RD::VertexAttribute vd; RID buffer; vd.location = i; @@ -2805,6 +3096,7 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su if (!(s->format & (1 << i))) { // Not supplied by surface, use default value buffer = mesh_default_rd_buffers[i]; + vd.stride = 0; switch (i) { case RS::ARRAY_VERTEX: { vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; @@ -2827,20 +3119,31 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su case RS::ARRAY_TEX_UV2: { vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; } break; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; case RS::ARRAY_BONES: { //assumed weights too vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; } break; + case RS::ARRAY_WEIGHTS: { + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + } break; } } else { //Supplied, use it - vd.offset = stride; - vd.stride = 1; //mark that it needs a stride set - buffer = s->vertex_buffer; + vd.stride = 1; //mark that it needs a stride set (default uses 0) switch (i) { case RS::ARRAY_VERTEX: { + vd.offset = stride; + if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) { vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; stride += sizeof(float) * 2; @@ -2849,71 +3152,92 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su stride += sizeof(float) * 3; } + if (mis) { + buffer = mis->vertex_buffer; + } else { + buffer = s->vertex_buffer; + } + } break; case RS::ARRAY_NORMAL: { - if (s->format & RS::ARRAY_COMPRESS_NORMAL) { - vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM; - stride += sizeof(int8_t) * 4; + vd.offset = stride; + + vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + + stride += sizeof(uint32_t); + if (mis) { + buffer = mis->vertex_buffer; } else { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - stride += sizeof(float) * 4; + buffer = s->vertex_buffer; } - } break; case RS::ARRAY_TANGENT: { - if (s->format & RS::ARRAY_COMPRESS_TANGENT) { - vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM; - stride += sizeof(int8_t) * 4; + vd.offset = stride; + + vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + stride += sizeof(uint32_t); + if (mis) { + buffer = mis->vertex_buffer; } else { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - stride += sizeof(float) * 4; + buffer = s->vertex_buffer; } - } break; case RS::ARRAY_COLOR: { - if (s->format & RS::ARRAY_COMPRESS_COLOR) { - vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - stride += sizeof(int8_t) * 4; - } else { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - stride += sizeof(float) * 4; - } + vd.offset = attribute_stride; + vd.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + attribute_stride += sizeof(int16_t) * 4; + buffer = s->attribute_buffer; } break; case RS::ARRAY_TEX_UV: { - if (s->format & RS::ARRAY_COMPRESS_TEX_UV) { - vd.format = RD::DATA_FORMAT_R16G16_SFLOAT; - stride += sizeof(int16_t) * 2; - } else { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - stride += sizeof(float) * 2; - } + vd.offset = attribute_stride; + + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + attribute_stride += sizeof(float) * 2; + buffer = s->attribute_buffer; } break; case RS::ARRAY_TEX_UV2: { - if (s->format & RS::ARRAY_COMPRESS_TEX_UV2) { - vd.format = RD::DATA_FORMAT_R16G16_SFLOAT; - stride += sizeof(int16_t) * 2; - } else { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - stride += sizeof(float) * 2; - } + vd.offset = attribute_stride; + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + attribute_stride += sizeof(float) * 2; + buffer = s->attribute_buffer; + } break; + case RS::ARRAY_CUSTOM0: + case RS::ARRAY_CUSTOM1: + case RS::ARRAY_CUSTOM2: + case RS::ARRAY_CUSTOM3: { + vd.offset = attribute_stride; + + int idx = i - RS::ARRAY_CUSTOM0; + uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT }; + uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK; + uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 }; + RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT }; + vd.format = fmtrd[fmt]; + attribute_stride += fmtsize[fmt]; + buffer = s->attribute_buffer; } break; case RS::ARRAY_BONES: { - //assumed weights too + vd.offset = skin_stride; - //unique format, internally 16 bits, exposed as single array for 32 - - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - stride += sizeof(int32_t) * 4; + vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT; + skin_stride += sizeof(int16_t) * 4; + buffer = s->skin_buffer; + } break; + case RS::ARRAY_WEIGHTS: { + vd.offset = skin_stride; + vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM; + skin_stride += sizeof(int16_t) * 4; + buffer = s->skin_buffer; } break; } } if (!(p_input_mask & (1 << i))) { - continue; // Shader does not need this, skip it + continue; // Shader does not need this, skip it (but computing stride was important anyway) } attributes.push_back(vd); @@ -2922,8 +3246,17 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su //update final stride for (int i = 0; i < attributes.size(); i++) { - if (attributes[i].stride == 1) { + if (attributes[i].stride == 0) { + continue; //default location + } + int loc = attributes[i].location; + + if (loc < RS::ARRAY_COLOR) { attributes.write[i].stride = stride; + } else if (loc < RS::ARRAY_BONES) { + attributes.write[i].stride = attribute_stride; + } else { + attributes.write[i].stride = skin_stride; } } @@ -2934,11 +3267,11 @@ void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Su ////////////////// MULTIMESH -RID RasterizerStorageRD::multimesh_create() { +RID RendererStorageRD::multimesh_create() { return multimesh_owner.make_rid(MultiMesh()); } -void RasterizerStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { +void RendererStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); @@ -2976,15 +3309,17 @@ void RasterizerStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, R if (multimesh->instances) { multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); } + + multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH); } -int RasterizerStorageRD::multimesh_get_instance_count(RID p_multimesh) const { +int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, 0); return multimesh->instances; } -void RasterizerStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { +void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); if (multimesh->mesh == p_mesh) { @@ -3009,12 +3344,12 @@ void RasterizerStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { } } - multimesh->instance_dependency.instance_notify_changed(true, true); + multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH); } #define MULTIMESH_DIRTY_REGION_SIZE 512 -void RasterizerStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { +void RendererStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { if (multimesh->data_cache.size() > 0) { return; //already local } @@ -3043,7 +3378,7 @@ void RasterizerStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { multimesh->data_cache_used_dirty_regions = 0; } -void RasterizerStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { +void RendererStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; #ifdef DEBUG_ENABLED uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; @@ -3065,7 +3400,7 @@ void RasterizerStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_inde } } -void RasterizerStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { +void RendererStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { if (p_data) { uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; @@ -3088,7 +3423,7 @@ void RasterizerStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p } } -void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { +void RendererStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { ERR_FAIL_COND(multimesh->mesh.is_null()); AABB aabb; AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); @@ -3130,7 +3465,7 @@ void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const multimesh->aabb = aabb; } -void RasterizerStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) { +void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_INDEX(p_index, multimesh->instances); @@ -3160,7 +3495,7 @@ void RasterizerStorageRD::multimesh_instance_set_transform(RID p_multimesh, int _multimesh_mark_dirty(multimesh, p_index, true); } -void RasterizerStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { +void RendererStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_INDEX(p_index, multimesh->instances); @@ -3186,7 +3521,7 @@ void RasterizerStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, i _multimesh_mark_dirty(multimesh, p_index, true); } -void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { +void RendererStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_INDEX(p_index, multimesh->instances); @@ -3208,7 +3543,7 @@ void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_in _multimesh_mark_dirty(multimesh, p_index, false); } -void RasterizerStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { +void RendererStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_INDEX(p_index, multimesh->instances); @@ -3230,14 +3565,14 @@ void RasterizerStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, in _multimesh_mark_dirty(multimesh, p_index, false); } -RID RasterizerStorageRD::multimesh_get_mesh(RID p_multimesh) const { +RID RendererStorageRD::multimesh_get_mesh(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, RID()); return multimesh->mesh; } -Transform RasterizerStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { +Transform RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Transform()); ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform()); @@ -3268,7 +3603,7 @@ Transform RasterizerStorageRD::multimesh_instance_get_transform(RID p_multimesh, return t; } -Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { +Transform2D RendererStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Transform2D()); ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); @@ -3293,7 +3628,7 @@ Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multi return t; } -Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const { +Color RendererStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Color()); ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); @@ -3316,7 +3651,7 @@ Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_i return c; } -Color RasterizerStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { +Color RendererStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Color()); ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); @@ -3339,7 +3674,7 @@ Color RasterizerStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, i return c; } -void RasterizerStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) { +void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); @@ -3368,11 +3703,11 @@ void RasterizerStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<flo const float *data = p_buffer.ptr(); _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - multimesh->instance_dependency.instance_notify_changed(true, false); + multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } } -Vector<float> RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const { +Vector<float> RendererStorageRD::multimesh_get_buffer(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Vector<float>()); if (multimesh->buffer.is_null()) { @@ -3395,7 +3730,7 @@ Vector<float> RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const { } } -void RasterizerStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { +void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); @@ -3409,24 +3744,26 @@ void RasterizerStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p } multimesh->visible_instances = p_visible; + + multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); } -int RasterizerStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { +int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, 0); return multimesh->visible_instances; } -AABB RasterizerStorageRD::multimesh_get_aabb(RID p_multimesh) const { +AABB RendererStorageRD::multimesh_get_aabb(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, AABB()); if (multimesh->aabb_dirty) { - const_cast<RasterizerStorageRD *>(this)->_update_dirty_multimeshes(); + const_cast<RendererStorageRD *>(this)->_update_dirty_multimeshes(); } return multimesh->aabb; } -void RasterizerStorageRD::_update_dirty_multimeshes() { +void RendererStorageRD::_update_dirty_multimeshes() { while (multimesh_dirty_list) { MultiMesh *multimesh = multimesh_dirty_list; @@ -3466,7 +3803,7 @@ void RasterizerStorageRD::_update_dirty_multimeshes() { //aabb is dirty.. _multimesh_re_create_aabb(multimesh, data, visible_instances); multimesh->aabb_dirty = false; - multimesh->instance_dependency.instance_notify_changed(true, false); + multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } } @@ -3481,25 +3818,25 @@ void RasterizerStorageRD::_update_dirty_multimeshes() { /* PARTICLES */ -RID RasterizerStorageRD::particles_create() { +RID RendererStorageRD::particles_create() { return particles_owner.make_rid(Particles()); } -void RasterizerStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) { +void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->emitting = p_emitting; } -bool RasterizerStorageRD::particles_get_emitting(RID p_particles) { +bool RendererStorageRD::particles_get_emitting(RID p_particles) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, false); return particles->emitting; } -void RasterizerStorageRD::_particles_free_data(Particles *particles) { +void RendererStorageRD::_particles_free_data(Particles *particles) { if (!particles->particle_buffer.is_valid()) { return; } @@ -3526,7 +3863,7 @@ void RasterizerStorageRD::_particles_free_data(Particles *particles) { } } -void RasterizerStorageRD::particles_set_amount(RID p_particles, int p_amount) { +void RendererStorageRD::particles_set_amount(RID p_particles, int p_amount) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); @@ -3549,14 +3886,14 @@ void RasterizerStorageRD::particles_set_amount(RID p_particles, int p_amount) { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; u.ids.push_back(particles->particle_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; u.ids.push_back(particles->particle_instance_buffer); uniforms.push_back(u); @@ -3572,111 +3909,111 @@ void RasterizerStorageRD::particles_set_amount(RID p_particles, int p_amount) { particles->clear = true; } -void RasterizerStorageRD::particles_set_lifetime(RID p_particles, float p_lifetime) { +void RendererStorageRD::particles_set_lifetime(RID p_particles, float p_lifetime) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->lifetime = p_lifetime; } -void RasterizerStorageRD::particles_set_one_shot(RID p_particles, bool p_one_shot) { +void RendererStorageRD::particles_set_one_shot(RID p_particles, bool p_one_shot) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->one_shot = p_one_shot; } -void RasterizerStorageRD::particles_set_pre_process_time(RID p_particles, float p_time) { +void RendererStorageRD::particles_set_pre_process_time(RID p_particles, float p_time) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->pre_process_time = p_time; } -void RasterizerStorageRD::particles_set_explosiveness_ratio(RID p_particles, float p_ratio) { +void RendererStorageRD::particles_set_explosiveness_ratio(RID p_particles, float p_ratio) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->explosiveness = p_ratio; } -void RasterizerStorageRD::particles_set_randomness_ratio(RID p_particles, float p_ratio) { +void RendererStorageRD::particles_set_randomness_ratio(RID p_particles, float p_ratio) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->randomness = p_ratio; } -void RasterizerStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { +void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->custom_aabb = p_aabb; - particles->instance_dependency.instance_notify_changed(true, false); + particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -void RasterizerStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) { +void RendererStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->speed_scale = p_scale; } -void RasterizerStorageRD::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { +void RendererStorageRD::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->use_local_coords = p_enable; } -void RasterizerStorageRD::particles_set_fixed_fps(RID p_particles, int p_fps) { +void RendererStorageRD::particles_set_fixed_fps(RID p_particles, int p_fps) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->fixed_fps = p_fps; } -void RasterizerStorageRD::particles_set_fractional_delta(RID p_particles, bool p_enable) { +void RendererStorageRD::particles_set_fractional_delta(RID p_particles, bool p_enable) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->fractional_delta = p_enable; } -void RasterizerStorageRD::particles_set_collision_base_size(RID p_particles, float p_size) { +void RendererStorageRD::particles_set_collision_base_size(RID p_particles, float p_size) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->collision_base_size = p_size; } -void RasterizerStorageRD::particles_set_process_material(RID p_particles, RID p_material) { +void RendererStorageRD::particles_set_process_material(RID p_particles, RID p_material) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->process_material = p_material; } -void RasterizerStorageRD::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { +void RendererStorageRD::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->draw_order = p_order; } -void RasterizerStorageRD::particles_set_draw_passes(RID p_particles, int p_passes) { +void RendererStorageRD::particles_set_draw_passes(RID p_particles, int p_passes) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->draw_passes.resize(p_passes); } -void RasterizerStorageRD::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { +void RendererStorageRD::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); particles->draw_passes.write[p_pass] = p_mesh; } -void RasterizerStorageRD::particles_restart(RID p_particles) { +void RendererStorageRD::particles_restart(RID p_particles) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->restart_request = true; } -void RasterizerStorageRD::_particles_allocate_emission_buffer(Particles *particles) { +void RendererStorageRD::_particles_allocate_emission_buffer(Particles *particles) { ERR_FAIL_COND(particles->emission_buffer != nullptr); particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4); @@ -3693,7 +4030,7 @@ void RasterizerStorageRD::_particles_allocate_emission_buffer(Particles *particl } } -void RasterizerStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { +void RendererStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_COND(p_particles == p_subemitter_particles); @@ -3706,7 +4043,7 @@ void RasterizerStorageRD::particles_set_subemitter(RID p_particles, RID p_subemi } } -void RasterizerStorageRD::particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { +void RendererStorageRD::particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_COND(particles->amount == 0); @@ -3749,7 +4086,7 @@ void RasterizerStorageRD::particles_emit(RID p_particles, const Transform &p_tra } } -void RasterizerStorageRD::particles_request_process(RID p_particles) { +void RendererStorageRD::particles_request_process(RID p_particles) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); @@ -3760,7 +4097,7 @@ void RasterizerStorageRD::particles_request_process(RID p_particles) { } } -AABB RasterizerStorageRD::particles_get_current_aabb(RID p_particles) { +AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) { const Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, AABB()); @@ -3804,28 +4141,28 @@ AABB RasterizerStorageRD::particles_get_current_aabb(RID p_particles) { return aabb; } -AABB RasterizerStorageRD::particles_get_aabb(RID p_particles) const { +AABB RendererStorageRD::particles_get_aabb(RID p_particles) const { const Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, AABB()); return particles->custom_aabb; } -void RasterizerStorageRD::particles_set_emission_transform(RID p_particles, const Transform &p_transform) { +void RendererStorageRD::particles_set_emission_transform(RID p_particles, const Transform &p_transform) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); particles->emission_transform = p_transform; } -int RasterizerStorageRD::particles_get_draw_passes(RID p_particles) const { +int RendererStorageRD::particles_get_draw_passes(RID p_particles) const { const Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, 0); return particles->draw_passes.size(); } -RID RasterizerStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { +RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { const Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, RID()); ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID()); @@ -3833,36 +4170,34 @@ RID RasterizerStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pas return particles->draw_passes[p_pass]; } -void RasterizerStorageRD::particles_add_collision(RID p_particles, RasterizerScene::InstanceBase *p_instance) { +void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_PARTICLES_COLLISION); - - particles->collisions.insert(p_instance); + particles->collisions.insert(p_particles_collision_instance); } -void RasterizerStorageRD::particles_remove_collision(RID p_particles, RasterizerScene::InstanceBase *p_instance) { +void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->collisions.erase(p_instance); + particles->collisions.erase(p_particles_collision_instance); } -void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_delta) { +void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) { if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) { Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; u.ids.push_back(p_particles->frame_params_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; u.ids.push_back(p_particles->particle_buffer); uniforms.push_back(u); @@ -3870,7 +4205,7 @@ void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_del { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; if (p_particles->emission_storage_buffer.is_valid()) { u.ids.push_back(p_particles->emission_storage_buffer); @@ -3881,7 +4216,7 @@ void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_del } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 3; Particles *sub_emitter = particles_owner.getornull(p_particles->sub_emitter); if (sub_emitter) { @@ -3918,7 +4253,7 @@ void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_del p_particles->phase = new_phase; - frame_params.time = RasterizerRD::singleton->get_total_time(); + frame_params.time = RendererCompositorRD::singleton->get_total_time(); frame_params.delta = p_delta * p_particles->speed_scale; frame_params.random_seed = p_particles->random_seed; frame_params.explosiveness = p_particles->explosiveness; @@ -3946,9 +4281,15 @@ void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_del to_particles = p_particles->emission_transform.affine_inverse(); } uint32_t collision_3d_textures_used = 0; - for (const Set<RasterizerScene::InstanceBase *>::Element *E = p_particles->collisions.front(); E; E = E->next()) { - ParticlesCollision *pc = particles_collision_owner.getornull(E->get()->base); - Transform to_collider = E->get()->transform; + for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { + ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(E->get()); + if (!pci || !pci->active) { + continue; + } + ParticlesCollision *pc = particles_collision_owner.getornull(pci->collision); + ERR_CONTINUE(!pc); + + Transform to_collider = pci->transform; if (p_particles->use_local_coords) { to_collider = to_particles * to_collider; } @@ -4088,7 +4429,7 @@ void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_del { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) { RID rd_tex; @@ -4108,7 +4449,7 @@ void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_del } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; if (collision_heightmap_texture.is_valid()) { u.ids.push_back(collision_heightmap_texture); @@ -4188,7 +4529,7 @@ void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_del RD::get_singleton()->compute_list_end(); } -void RasterizerStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &p_axis) { +void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &p_axis) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); @@ -4209,7 +4550,7 @@ void RasterizerStorageRD::particles_set_view_axis(RID p_particles, const Vector3 { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; u.ids.push_back(particles->particles_sort_buffer); uniforms.push_back(u); @@ -4254,7 +4595,7 @@ void RasterizerStorageRD::particles_set_view_axis(RID p_particles, const Vector3 RD::get_singleton()->compute_list_end(); } -void RasterizerStorageRD::update_particles() { +void RendererStorageRD::update_particles() { while (particle_update_list) { //use transform feedback to process particles @@ -4289,7 +4630,7 @@ void RasterizerStorageRD::update_particles() { particles->inactive = false; particles->inactive_time = 0; } else { - particles->inactive_time += particles->speed_scale * RasterizerRD::singleton->get_frame_delta_time(); + particles->inactive_time += particles->speed_scale * RendererCompositorRD::singleton->get_frame_delta_time(); if (particles->inactive_time > particles->lifetime * 1.2) { particles->inactive = true; continue; @@ -4323,7 +4664,7 @@ void RasterizerStorageRD::update_particles() { frame_time = 1.0 / particles->fixed_fps; decr = frame_time; } - float delta = RasterizerRD::singleton->get_frame_delta_time(); + float delta = RendererCompositorRD::singleton->get_frame_delta_time(); if (delta > 0.1) { //avoid recursive stalls if fps goes below 10 delta = 0.1; } else if (delta <= 0.0) { //unlikely but.. @@ -4342,7 +4683,7 @@ void RasterizerStorageRD::update_particles() { if (zero_time_scale) _particles_process(particles, 0.0); else - _particles_process(particles, RasterizerRD::singleton->get_frame_delta_time()); + _particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time()); } //copy particles to instance buffer @@ -4361,11 +4702,11 @@ void RasterizerStorageRD::update_particles() { RD::get_singleton()->compute_list_end(); } - particles->instance_dependency.instance_notify_changed(true, false); //make sure shadows are updated + particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } } -bool RasterizerStorageRD::particles_is_inactive(RID p_particles) const { +bool RendererStorageRD::particles_is_inactive(RID p_particles) const { const Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, false); return !particles->emitting && particles->inactive; @@ -4373,7 +4714,7 @@ bool RasterizerStorageRD::particles_is_inactive(RID p_particles) const { /* SKY SHADER */ -void RasterizerStorageRD::ParticlesShaderData::set_code(const String &p_code) { +void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) { //compile code = p_code; @@ -4421,7 +4762,7 @@ void RasterizerStorageRD::ParticlesShaderData::set_code(const String &p_code) { valid = true; } -void RasterizerStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { +void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { if (!p_texture.is_valid()) { default_texture_params.erase(p_name); } else { @@ -4429,7 +4770,7 @@ void RasterizerStorageRD::ParticlesShaderData::set_default_texture_param(const S } } -void RasterizerStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { +void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { Map<int, StringName> order; for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { @@ -4451,13 +4792,13 @@ void RasterizerStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> } } -void RasterizerStorageRD::ParticlesShaderData::get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const { +void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const { for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - RasterizerStorage::InstanceShaderParam p; + RendererStorage::InstanceShaderParam p; p.info = ShaderLanguage::uniform_to_property_info(E->get()); p.info.name = E->key(); //supply name p.index = E->get().instance_index; @@ -4466,7 +4807,7 @@ void RasterizerStorageRD::ParticlesShaderData::get_instance_param_list(List<Rast } } -bool RasterizerStorageRD::ParticlesShaderData::is_param_texture(const StringName &p_param) const { +bool RendererStorageRD::ParticlesShaderData::is_param_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -4474,15 +4815,15 @@ bool RasterizerStorageRD::ParticlesShaderData::is_param_texture(const StringName return uniforms[p_param].texture_order >= 0; } -bool RasterizerStorageRD::ParticlesShaderData::is_animated() const { +bool RendererStorageRD::ParticlesShaderData::is_animated() const { return false; } -bool RasterizerStorageRD::ParticlesShaderData::casts_shadows() const { +bool RendererStorageRD::ParticlesShaderData::casts_shadows() const { return false; } -Variant RasterizerStorageRD::ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const { +Variant RendererStorageRD::ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const { if (uniforms.has(p_parameter)) { ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; @@ -4491,23 +4832,27 @@ Variant RasterizerStorageRD::ParticlesShaderData::get_default_parameter(const St return Variant(); } -RasterizerStorageRD::ParticlesShaderData::ParticlesShaderData() { +RS::ShaderNativeSourceCode RendererStorageRD::ParticlesShaderData::get_native_source_code() const { + return base_singleton->particles_shader.shader.version_get_native_source_code(version); +} + +RendererStorageRD::ParticlesShaderData::ParticlesShaderData() { valid = false; } -RasterizerStorageRD::ParticlesShaderData::~ParticlesShaderData() { +RendererStorageRD::ParticlesShaderData::~ParticlesShaderData() { //pipeline variants will clear themselves if shader is gone if (version.is_valid()) { base_singleton->particles_shader.shader.version_free(version); } } -RasterizerStorageRD::ShaderData *RasterizerStorageRD::_create_particles_shader_func() { +RendererStorageRD::ShaderData *RendererStorageRD::_create_particles_shader_func() { ParticlesShaderData *shader_data = memnew(ParticlesShaderData); return shader_data; } -void RasterizerStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +void RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { uniform_set_updated = true; if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { @@ -4568,7 +4913,7 @@ void RasterizerStorageRD::ParticlesMaterialData::update_parameters(const Map<Str { if (shader_data->ubo_size) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 0; u.ids.push_back(uniform_buffer); uniforms.push_back(u); @@ -4577,7 +4922,7 @@ void RasterizerStorageRD::ParticlesMaterialData::update_parameters(const Map<Str const RID *textures = texture_cache.ptrw(); for (uint32_t i = 0; i < tex_uniform_count; i++) { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1 + i; u.ids.push_back(textures[i]); uniforms.push_back(u); @@ -4587,7 +4932,7 @@ void RasterizerStorageRD::ParticlesMaterialData::update_parameters(const Map<Str uniform_set = RD::get_singleton()->uniform_set_create(uniforms, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); } -RasterizerStorageRD::ParticlesMaterialData::~ParticlesMaterialData() { +RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() { if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { RD::get_singleton()->free(uniform_set); } @@ -4597,7 +4942,7 @@ RasterizerStorageRD::ParticlesMaterialData::~ParticlesMaterialData() { } } -RasterizerStorageRD::MaterialData *RasterizerStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { +RendererStorageRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) { ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); material_data->shader_data = p_shader; material_data->last_frame = false; @@ -4608,11 +4953,11 @@ RasterizerStorageRD::MaterialData *RasterizerStorageRD::_create_particles_materi /* PARTICLES COLLISION API */ -RID RasterizerStorageRD::particles_collision_create() { +RID RendererStorageRD::particles_collision_create() { return particles_collision_owner.make_rid(ParticlesCollision()); } -RID RasterizerStorageRD::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const { +RID RendererStorageRD::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND_V(!particles_collision, RID()); ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID()); @@ -4633,7 +4978,7 @@ RID RasterizerStorageRD::particles_collision_get_heightfield_framebuffer(RID p_p tf.format = RD::DATA_FORMAT_D32_SFLOAT; tf.width = size.x; tf.height = size.y; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; particles_collision->heightfield_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -4647,7 +4992,7 @@ RID RasterizerStorageRD::particles_collision_get_heightfield_framebuffer(RID p_p return particles_collision->heightfield_fb; } -void RasterizerStorageRD::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) { +void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); @@ -4660,66 +5005,66 @@ void RasterizerStorageRD::particles_collision_set_collision_type(RID p_particles particles_collision->heightfield_texture = RID(); } particles_collision->type = p_type; - particles_collision->instance_dependency.instance_notify_changed(true, false); + particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -void RasterizerStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { +void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); particles_collision->cull_mask = p_cull_mask; } -void RasterizerStorageRD::particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) { +void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); particles_collision->radius = p_radius; - particles_collision->instance_dependency.instance_notify_changed(true, false); + particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -void RasterizerStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { +void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); particles_collision->extents = p_extents; - particles_collision->instance_dependency.instance_notify_changed(true, false); + particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -void RasterizerStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) { +void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); particles_collision->attractor_strength = p_strength; } -void RasterizerStorageRD::particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) { +void RendererStorageRD::particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); particles_collision->attractor_directionality = p_directionality; } -void RasterizerStorageRD::particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) { +void RendererStorageRD::particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); particles_collision->attractor_attenuation = p_curve; } -void RasterizerStorageRD::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) { +void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); particles_collision->field_texture = p_texture; } -void RasterizerStorageRD::particles_collision_height_field_update(RID p_particles_collision) { +void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); - particles_collision->instance_dependency.instance_notify_changed(true, false); + particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -void RasterizerStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { +void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND(!particles_collision); @@ -4735,7 +5080,7 @@ void RasterizerStorageRD::particles_collision_set_height_field_resolution(RID p_ } } -AABB RasterizerStorageRD::particles_collision_get_aabb(RID p_particles_collision) const { +AABB RendererStorageRD::particles_collision_get_aabb(RID p_particles_collision) const { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND_V(!particles_collision, AABB()); @@ -4758,25 +5103,41 @@ AABB RasterizerStorageRD::particles_collision_get_aabb(RID p_particles_collision return AABB(); } -Vector3 RasterizerStorageRD::particles_collision_get_extents(RID p_particles_collision) const { +Vector3 RendererStorageRD::particles_collision_get_extents(RID p_particles_collision) const { const ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND_V(!particles_collision, Vector3()); return particles_collision->extents; } -bool RasterizerStorageRD::particles_collision_is_heightfield(RID p_particles_collision) const { +bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_collision) const { const ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision); ERR_FAIL_COND_V(!particles_collision, false); return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE; } +RID RendererStorageRD::particles_collision_instance_create(RID p_collision) { + ParticlesCollisionInstance pci; + pci.collision = p_collision; + return particles_collision_instance_owner.make_rid(pci); +} +void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) { + ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance); + ERR_FAIL_COND(!pci); + pci->transform = p_transform; +} +void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) { + ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance); + ERR_FAIL_COND(!pci); + pci->active = p_active; +} + /* SKELETON API */ -RID RasterizerStorageRD::skeleton_create() { +RID RendererStorageRD::skeleton_create() { return skeleton_owner.make_rid(Skeleton()); } -void RasterizerStorageRD::_skeleton_make_dirty(Skeleton *skeleton) { +void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) { if (!skeleton->dirty) { skeleton->dirty = true; skeleton->dirty_list = skeleton_dirty_list; @@ -4784,7 +5145,7 @@ void RasterizerStorageRD::_skeleton_make_dirty(Skeleton *skeleton) { } } -void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) { +void RendererStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND(!skeleton); ERR_FAIL_COND(p_bones < 0); @@ -4801,6 +5162,7 @@ void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_ RD::get_singleton()->free(skeleton->buffer); skeleton->buffer = RID(); skeleton->data.resize(0); + skeleton->uniform_set_mi = RID(); } if (skeleton->size) { @@ -4809,17 +5171,31 @@ void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_ zeromem(skeleton->data.ptrw(), skeleton->data.size() * sizeof(float)); _skeleton_make_dirty(skeleton); + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(skeleton->buffer); + uniforms.push_back(u); + } + skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); + } } + + skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_DATA); } -int RasterizerStorageRD::skeleton_get_bone_count(RID p_skeleton) const { +int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND_V(!skeleton, 0); return skeleton->size; } -void RasterizerStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) { +void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND(!skeleton); @@ -4844,7 +5220,7 @@ void RasterizerStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone _skeleton_make_dirty(skeleton); } -Transform RasterizerStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { +Transform RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND_V(!skeleton, Transform()); @@ -4871,7 +5247,7 @@ Transform RasterizerStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p return t; } -void RasterizerStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { +void RendererStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND(!skeleton); @@ -4892,7 +5268,7 @@ void RasterizerStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_b _skeleton_make_dirty(skeleton); } -Transform2D RasterizerStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { +Transform2D RendererStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND_V(!skeleton, Transform2D()); @@ -4912,7 +5288,7 @@ Transform2D RasterizerStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, return t; } -void RasterizerStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { +void RendererStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND(!skeleton->use_2d); @@ -4920,7 +5296,7 @@ void RasterizerStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const T skeleton->base_transform_2d = p_base_transform; } -void RasterizerStorageRD::_update_dirty_skeletons() { +void RendererStorageRD::_update_dirty_skeletons() { while (skeleton_dirty_list) { Skeleton *skeleton = skeleton_dirty_list; @@ -4930,7 +5306,9 @@ void RasterizerStorageRD::_update_dirty_skeletons() { skeleton_dirty_list = skeleton->dirty_list; - skeleton->instance_dependency.instance_notify_changed(true, false); + skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES); + + skeleton->version++; skeleton->dirty = false; skeleton->dirty_list = nullptr; @@ -4941,7 +5319,7 @@ void RasterizerStorageRD::_update_dirty_skeletons() { /* LIGHT */ -RID RasterizerStorageRD::light_create(RS::LightType p_type) { +RID RendererStorageRD::light_create(RS::LightType p_type) { Light light; light.type = p_type; @@ -4950,29 +5328,32 @@ RID RasterizerStorageRD::light_create(RS::LightType p_type) { light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5; light.param[RS::LIGHT_PARAM_RANGE] = 1.0; light.param[RS::LIGHT_PARAM_SIZE] = 0.0; + light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0; light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45; + light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0; light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0; light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1; light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3; light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6; light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8; - light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02; light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0; + light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02; + light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0; light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0; - light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05; light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 1.0; + light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05; return light_owner.make_rid(light); } -void RasterizerStorageRD::light_set_color(RID p_light, const Color &p_color) { +void RendererStorageRD::light_set_color(RID p_light, const Color &p_color) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->color = p_color; } -void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, float p_value) { +void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, float p_value) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX); @@ -4988,7 +5369,7 @@ void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, f case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE: case RS::LIGHT_PARAM_SHADOW_BIAS: { light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } break; default: { } @@ -4997,22 +5378,22 @@ void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, f light->param[p_param] = p_value; } -void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) { +void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->shadow = p_enabled; light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } -void RasterizerStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) { +void RendererStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->shadow_color = p_color; } -void RasterizerStorageRD::light_set_projector(RID p_light, RID p_texture) { +void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); @@ -5031,138 +5412,152 @@ void RasterizerStorageRD::light_set_projector(RID p_light, RID p_texture) { } } -void RasterizerStorageRD::light_set_negative(RID p_light, bool p_enable) { +void RendererStorageRD::light_set_negative(RID p_light, bool p_enable) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->negative = p_enable; } -void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) { +void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->cull_mask = p_mask; light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } -void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { +void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->reverse_cull = p_enabled; light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } -void RasterizerStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { +void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->bake_mode = p_bake_mode; light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } -void RasterizerStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) { +void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->max_sdfgi_cascade = p_cascade; light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } -void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { +void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->omni_shadow_mode = p_mode; light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } -RS::LightOmniShadowMode RasterizerStorageRD::light_omni_get_shadow_mode(RID p_light) { +RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE); return light->omni_shadow_mode; } -void RasterizerStorageRD::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) { +void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->directional_shadow_mode = p_mode; light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } -void RasterizerStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) { +void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->directional_blend_splits = p_enable; light->version++; - light->instance_dependency.instance_notify_changed(true, false); + light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT); } -bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const { +bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, false); return light->directional_blend_splits; } -RS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) { +void RendererStorageRD::light_directional_set_sky_only(RID p_light, bool p_sky_only) { + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->directional_sky_only = p_sky_only; +} + +bool RendererStorageRD::light_directional_is_sky_only(RID p_light) const { + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, false); + + return light->directional_sky_only; +} + +RS::LightDirectionalShadowMode RendererStorageRD::light_directional_get_shadow_mode(RID p_light) { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); return light->directional_shadow_mode; } -void RasterizerStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) { +void RendererStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->directional_range_mode = p_range_mode; } -RS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const { +RS::LightDirectionalShadowDepthRangeMode RendererStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); return light->directional_range_mode; } -uint32_t RasterizerStorageRD::light_get_max_sdfgi_cascade(RID p_light) { +uint32_t RendererStorageRD::light_get_max_sdfgi_cascade(RID p_light) { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, 0); return light->max_sdfgi_cascade; } -RS::LightBakeMode RasterizerStorageRD::light_get_bake_mode(RID p_light) { +RS::LightBakeMode RendererStorageRD::light_get_bake_mode(RID p_light) { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED); return light->bake_mode; } -uint64_t RasterizerStorageRD::light_get_version(RID p_light) const { +uint64_t RendererStorageRD::light_get_version(RID p_light) const { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, 0); return light->version; } -AABB RasterizerStorageRD::light_get_aabb(RID p_light) const { +AABB RendererStorageRD::light_get_aabb(RID p_light) const { const Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, AABB()); @@ -5186,56 +5581,56 @@ AABB RasterizerStorageRD::light_get_aabb(RID p_light) const { /* REFLECTION PROBE */ -RID RasterizerStorageRD::reflection_probe_create() { +RID RendererStorageRD::reflection_probe_create() { return reflection_probe_owner.make_rid(ReflectionProbe()); } -void RasterizerStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) { +void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->update_mode = p_mode; - reflection_probe->instance_dependency.instance_notify_changed(true, false); + reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) { +void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->intensity = p_intensity; } -void RasterizerStorageRD::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) { +void RendererStorageRD::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->ambient_mode = p_mode; } -void RasterizerStorageRD::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) { +void RendererStorageRD::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->ambient_color = p_color; } -void RasterizerStorageRD::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) { +void RendererStorageRD::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->ambient_color_energy = p_energy; } -void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) { +void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->max_distance = p_distance; - reflection_probe->instance_dependency.instance_notify_changed(true, false); + reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { +void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); @@ -5243,49 +5638,49 @@ void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector return; } reflection_probe->extents = p_extents; - reflection_probe->instance_dependency.instance_notify_changed(true, false); + reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { +void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->origin_offset = p_offset; - reflection_probe->instance_dependency.instance_notify_changed(true, false); + reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void RasterizerStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { +void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->interior = p_enable; - reflection_probe->instance_dependency.instance_notify_changed(true, false); + reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { +void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->box_projection = p_enable; } -void RasterizerStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) { +void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->enable_shadows = p_enable; - reflection_probe->instance_dependency.instance_notify_changed(true, false); + reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { +void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); reflection_probe->cull_mask = p_layers; - reflection_probe->instance_dependency.instance_notify_changed(true, false); + reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void RasterizerStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) { +void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); ERR_FAIL_COND(p_resolution < 32); @@ -5293,7 +5688,16 @@ void RasterizerStorageRD::reflection_probe_set_resolution(RID p_probe, int p_res reflection_probe->resolution = p_resolution; } -AABB RasterizerStorageRD::reflection_probe_get_aabb(RID p_probe) const { +void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) { + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->lod_threshold = p_ratio; + + reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE); +} + +AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, AABB()); @@ -5304,107 +5708,114 @@ AABB RasterizerStorageRD::reflection_probe_get_aabb(RID p_probe) const { return aabb; } -RS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_mode(RID p_probe) const { +RS::ReflectionProbeUpdateMode RendererStorageRD::reflection_probe_get_update_mode(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS); return reflection_probe->update_mode; } -uint32_t RasterizerStorageRD::reflection_probe_get_cull_mask(RID p_probe) const { +uint32_t RendererStorageRD::reflection_probe_get_cull_mask(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, 0); return reflection_probe->cull_mask; } -Vector3 RasterizerStorageRD::reflection_probe_get_extents(RID p_probe) const { +Vector3 RendererStorageRD::reflection_probe_get_extents(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, Vector3()); return reflection_probe->extents; } -Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) const { +Vector3 RendererStorageRD::reflection_probe_get_origin_offset(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, Vector3()); return reflection_probe->origin_offset; } -bool RasterizerStorageRD::reflection_probe_renders_shadows(RID p_probe) const { +bool RendererStorageRD::reflection_probe_renders_shadows(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, false); return reflection_probe->enable_shadows; } -float RasterizerStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const { +float RendererStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, 0); return reflection_probe->max_distance; } -int RasterizerStorageRD::reflection_probe_get_resolution(RID p_probe) const { +float RendererStorageRD::reflection_probe_get_lod_threshold(RID p_probe) const { + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, 0); + + return reflection_probe->lod_threshold; +} + +int RendererStorageRD::reflection_probe_get_resolution(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, 0); return reflection_probe->resolution; } -float RasterizerStorageRD::reflection_probe_get_intensity(RID p_probe) const { +float RendererStorageRD::reflection_probe_get_intensity(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, 0); return reflection_probe->intensity; } -bool RasterizerStorageRD::reflection_probe_is_interior(RID p_probe) const { +bool RendererStorageRD::reflection_probe_is_interior(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, false); return reflection_probe->interior; } -bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const { +bool RendererStorageRD::reflection_probe_is_box_projection(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, false); return reflection_probe->box_projection; } -RS::ReflectionProbeAmbientMode RasterizerStorageRD::reflection_probe_get_ambient_mode(RID p_probe) const { +RS::ReflectionProbeAmbientMode RendererStorageRD::reflection_probe_get_ambient_mode(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED); return reflection_probe->ambient_mode; } -Color RasterizerStorageRD::reflection_probe_get_ambient_color(RID p_probe) const { +Color RendererStorageRD::reflection_probe_get_ambient_color(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, Color()); return reflection_probe->ambient_color; } -float RasterizerStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe) const { +float RendererStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, 0); return reflection_probe->ambient_color_energy; } -RID RasterizerStorageRD::decal_create() { +RID RendererStorageRD::decal_create() { return decal_owner.make_rid(Decal()); } -void RasterizerStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) { +void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); decal->extents = p_extents; - decal->instance_dependency.instance_notify_changed(true, false); + decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -void RasterizerStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { +void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX); @@ -5425,35 +5836,35 @@ void RasterizerStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type texture_add_to_decal_atlas(decal->textures[p_type]); } - decal->instance_dependency.instance_notify_changed(false, true); + decal->dependency.changed_notify(DEPENDENCY_CHANGED_DECAL); } -void RasterizerStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) { +void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); decal->emission_energy = p_energy; } -void RasterizerStorageRD::decal_set_albedo_mix(RID p_decal, float p_mix) { +void RendererStorageRD::decal_set_albedo_mix(RID p_decal, float p_mix) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); decal->albedo_mix = p_mix; } -void RasterizerStorageRD::decal_set_modulate(RID p_decal, const Color &p_modulate) { +void RendererStorageRD::decal_set_modulate(RID p_decal, const Color &p_modulate) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); decal->modulate = p_modulate; } -void RasterizerStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) { +void RendererStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); decal->cull_mask = p_layers; - decal->instance_dependency.instance_notify_changed(true, false); + decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -void RasterizerStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { +void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); decal->distance_fade = p_enabled; @@ -5461,31 +5872,31 @@ void RasterizerStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, f decal->distance_fade_length = p_length; } -void RasterizerStorageRD::decal_set_fade(RID p_decal, float p_above, float p_below) { +void RendererStorageRD::decal_set_fade(RID p_decal, float p_above, float p_below) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); decal->upper_fade = p_above; decal->lower_fade = p_below; } -void RasterizerStorageRD::decal_set_normal_fade(RID p_decal, float p_fade) { +void RendererStorageRD::decal_set_normal_fade(RID p_decal, float p_fade) { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND(!decal); decal->normal_fade = p_fade; } -AABB RasterizerStorageRD::decal_get_aabb(RID p_decal) const { +AABB RendererStorageRD::decal_get_aabb(RID p_decal) const { Decal *decal = decal_owner.getornull(p_decal); ERR_FAIL_COND_V(!decal, AABB()); return AABB(-decal->extents, decal->extents * 2.0); } -RID RasterizerStorageRD::gi_probe_create() { +RID RendererStorageRD::gi_probe_create() { return gi_probe_owner.make_rid(GIProbe()); } -void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) { +void RendererStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); @@ -5528,7 +5939,7 @@ void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_t tf.width = gi_probe->octree_size.x; tf.height = gi_probe->octree_size.y; tf.depth = gi_probe->octree_size.z; - tf.type = RD::TEXTURE_TYPE_3D; + tf.texture_type = RD::TEXTURE_TYPE_3D; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; Vector<Vector<uint8_t>> s; s.push_back(p_distance_field); @@ -5557,21 +5968,21 @@ void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_t Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; u.ids.push_back(gi_probe->octree_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; u.ids.push_back(gi_probe->data_buffer); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; u.ids.push_back(shared_tex); uniforms.push_back(u); @@ -5607,23 +6018,23 @@ void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_t gi_probe->version++; gi_probe->data_version++; - gi_probe->instance_dependency.instance_notify_changed(true, false); + gi_probe->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); } -AABB RasterizerStorageRD::gi_probe_get_bounds(RID p_gi_probe) const { +AABB RendererStorageRD::gi_probe_get_bounds(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, AABB()); return gi_probe->bounds; } -Vector3i RasterizerStorageRD::gi_probe_get_octree_size(RID p_gi_probe) const { +Vector3i RendererStorageRD::gi_probe_get_octree_size(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, Vector3i()); return gi_probe->octree_size; } -Vector<uint8_t> RasterizerStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) const { +Vector<uint8_t> RendererStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>()); @@ -5633,7 +6044,7 @@ Vector<uint8_t> RasterizerStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) c return Vector<uint8_t>(); } -Vector<uint8_t> RasterizerStorageRD::gi_probe_get_data_cells(RID p_gi_probe) const { +Vector<uint8_t> RendererStorageRD::gi_probe_get_data_cells(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>()); @@ -5643,7 +6054,7 @@ Vector<uint8_t> RasterizerStorageRD::gi_probe_get_data_cells(RID p_gi_probe) con return Vector<uint8_t>(); } -Vector<uint8_t> RasterizerStorageRD::gi_probe_get_distance_field(RID p_gi_probe) const { +Vector<uint8_t> RendererStorageRD::gi_probe_get_distance_field(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, Vector<uint8_t>()); @@ -5653,21 +6064,21 @@ Vector<uint8_t> RasterizerStorageRD::gi_probe_get_distance_field(RID p_gi_probe) return Vector<uint8_t>(); } -Vector<int> RasterizerStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const { +Vector<int> RendererStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, Vector<int>()); return gi_probe->level_counts; } -Transform RasterizerStorageRD::gi_probe_get_to_cell_xform(RID p_gi_probe) const { +Transform RendererStorageRD::gi_probe_get_to_cell_xform(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, Transform()); return gi_probe->to_cell_xform; } -void RasterizerStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) { +void RendererStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); @@ -5675,14 +6086,14 @@ void RasterizerStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_ran gi_probe->version++; } -float RasterizerStorageRD::gi_probe_get_dynamic_range(RID p_gi_probe) const { +float RendererStorageRD::gi_probe_get_dynamic_range(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->dynamic_range; } -void RasterizerStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range) { +void RendererStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); @@ -5690,98 +6101,98 @@ void RasterizerStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range gi_probe->version++; } -float RasterizerStorageRD::gi_probe_get_propagation(RID p_gi_probe) const { +float RendererStorageRD::gi_probe_get_propagation(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->propagation; } -void RasterizerStorageRD::gi_probe_set_energy(RID p_gi_probe, float p_energy) { +void RendererStorageRD::gi_probe_set_energy(RID p_gi_probe, float p_energy) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); gi_probe->energy = p_energy; } -float RasterizerStorageRD::gi_probe_get_energy(RID p_gi_probe) const { +float RendererStorageRD::gi_probe_get_energy(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->energy; } -void RasterizerStorageRD::gi_probe_set_ao(RID p_gi_probe, float p_ao) { +void RendererStorageRD::gi_probe_set_ao(RID p_gi_probe, float p_ao) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); gi_probe->ao = p_ao; } -float RasterizerStorageRD::gi_probe_get_ao(RID p_gi_probe) const { +float RendererStorageRD::gi_probe_get_ao(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->ao; } -void RasterizerStorageRD::gi_probe_set_ao_size(RID p_gi_probe, float p_strength) { +void RendererStorageRD::gi_probe_set_ao_size(RID p_gi_probe, float p_strength) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); gi_probe->ao_size = p_strength; } -float RasterizerStorageRD::gi_probe_get_ao_size(RID p_gi_probe) const { +float RendererStorageRD::gi_probe_get_ao_size(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->ao_size; } -void RasterizerStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) { +void RendererStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); gi_probe->bias = p_bias; } -float RasterizerStorageRD::gi_probe_get_bias(RID p_gi_probe) const { +float RendererStorageRD::gi_probe_get_bias(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->bias; } -void RasterizerStorageRD::gi_probe_set_normal_bias(RID p_gi_probe, float p_normal_bias) { +void RendererStorageRD::gi_probe_set_normal_bias(RID p_gi_probe, float p_normal_bias) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); gi_probe->normal_bias = p_normal_bias; } -float RasterizerStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const { +float RendererStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->normal_bias; } -void RasterizerStorageRD::gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) { +void RendererStorageRD::gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); gi_probe->anisotropy_strength = p_strength; } -float RasterizerStorageRD::gi_probe_get_anisotropy_strength(RID p_gi_probe) const { +float RendererStorageRD::gi_probe_get_anisotropy_strength(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->anisotropy_strength; } -void RasterizerStorageRD::gi_probe_set_interior(RID p_gi_probe, bool p_enable) { +void RendererStorageRD::gi_probe_set_interior(RID p_gi_probe, bool p_enable) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); gi_probe->interior = p_enable; } -void RasterizerStorageRD::gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) { +void RendererStorageRD::gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND(!gi_probe); @@ -5789,43 +6200,43 @@ void RasterizerStorageRD::gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_en gi_probe->version++; } -bool RasterizerStorageRD::gi_probe_is_using_two_bounces(RID p_gi_probe) const { +bool RendererStorageRD::gi_probe_is_using_two_bounces(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, false); return gi_probe->use_two_bounces; } -bool RasterizerStorageRD::gi_probe_is_interior(RID p_gi_probe) const { +bool RendererStorageRD::gi_probe_is_interior(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->interior; } -uint32_t RasterizerStorageRD::gi_probe_get_version(RID p_gi_probe) { +uint32_t RendererStorageRD::gi_probe_get_version(RID p_gi_probe) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->version; } -uint32_t RasterizerStorageRD::gi_probe_get_data_version(RID p_gi_probe) { +uint32_t RendererStorageRD::gi_probe_get_data_version(RID p_gi_probe) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, 0); return gi_probe->data_version; } -RID RasterizerStorageRD::gi_probe_get_octree_buffer(RID p_gi_probe) const { +RID RendererStorageRD::gi_probe_get_octree_buffer(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, RID()); return gi_probe->octree_buffer; } -RID RasterizerStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const { +RID RendererStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, RID()); return gi_probe->data_buffer; } -RID RasterizerStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) { +RID RendererStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) { GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); ERR_FAIL_COND_V(!gi_probe, RID()); @@ -5834,11 +6245,11 @@ RID RasterizerStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) { /* LIGHTMAP API */ -RID RasterizerStorageRD::lightmap_create() { +RID RendererStorageRD::lightmap_create() { return lightmap_owner.make_rid(Lightmap()); } -void RasterizerStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) { +void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND(!lm); @@ -5886,19 +6297,19 @@ void RasterizerStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, boo } } -void RasterizerStorageRD::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) { +void RendererStorageRD::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND(!lm); lm->bounds = p_bounds; } -void RasterizerStorageRD::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) { +void RendererStorageRD::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND(!lm); lm->interior = p_interior; } -void RasterizerStorageRD::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) { +void RendererStorageRD::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND(!lm); @@ -5914,36 +6325,36 @@ void RasterizerStorageRD::lightmap_set_probe_capture_data(RID p_lightmap, const lm->tetrahedra = p_tetrahedra; } -PackedVector3Array RasterizerStorageRD::lightmap_get_probe_capture_points(RID p_lightmap) const { +PackedVector3Array RendererStorageRD::lightmap_get_probe_capture_points(RID p_lightmap) const { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND_V(!lm, PackedVector3Array()); return lm->points; } -PackedColorArray RasterizerStorageRD::lightmap_get_probe_capture_sh(RID p_lightmap) const { +PackedColorArray RendererStorageRD::lightmap_get_probe_capture_sh(RID p_lightmap) const { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND_V(!lm, PackedColorArray()); return lm->point_sh; } -PackedInt32Array RasterizerStorageRD::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const { +PackedInt32Array RendererStorageRD::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND_V(!lm, PackedInt32Array()); return lm->tetrahedra; } -PackedInt32Array RasterizerStorageRD::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const { +PackedInt32Array RendererStorageRD::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND_V(!lm, PackedInt32Array()); return lm->bsp_tree; } -void RasterizerStorageRD::lightmap_set_probe_capture_update_speed(float p_speed) { +void RendererStorageRD::lightmap_set_probe_capture_update_speed(float p_speed) { lightmap_probe_capture_update_speed = p_speed; } -void RasterizerStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) { +void RendererStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) { Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND(!lm); @@ -5993,13 +6404,13 @@ void RasterizerStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p } } -bool RasterizerStorageRD::lightmap_is_interior(RID p_lightmap) const { +bool RendererStorageRD::lightmap_is_interior(RID p_lightmap) const { const Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND_V(!lm, false); return lm->interior; } -AABB RasterizerStorageRD::lightmap_get_aabb(RID p_lightmap) const { +AABB RendererStorageRD::lightmap_get_aabb(RID p_lightmap) const { const Lightmap *lm = lightmap_owner.getornull(p_lightmap); ERR_FAIL_COND_V(!lm, AABB()); return lm->bounds; @@ -6007,7 +6418,7 @@ AABB RasterizerStorageRD::lightmap_get_aabb(RID p_lightmap) const { /* RENDER TARGET API */ -void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) { +void RendererStorageRD::_clear_render_target(RenderTarget *rt) { //free in reverse dependency order if (rt->framebuffer.is_valid()) { RD::get_singleton()->free(rt->framebuffer); @@ -6035,7 +6446,7 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) { rt->color = RID(); } -void RasterizerStorageRD::_update_render_target(RenderTarget *rt) { +void RendererStorageRD::_update_render_target(RenderTarget *rt) { if (rt->texture.is_null()) { //create a placeholder until updated rt->texture = texture_2d_placeholder_create(); @@ -6062,7 +6473,7 @@ void RasterizerStorageRD::_update_render_target(RenderTarget *rt) { rd_format.depth = 1; rd_format.array_layers = 1; rd_format.mipmaps = 1; - rd_format.type = RD::TEXTURE_TYPE_2D; + rd_format.texture_type = RD::TEXTURE_TYPE_2D; rd_format.samples = RD::TEXTURE_SAMPLES_1; rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; rd_format.shareable_formats.push_back(rt->color_format); @@ -6123,7 +6534,7 @@ void RasterizerStorageRD::_update_render_target(RenderTarget *rt) { } } -void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) { +void RendererStorageRD::_create_render_target_backbuffer(RenderTarget *rt) { ERR_FAIL_COND(rt->backbuffer.is_valid()); uint32_t mipmaps_required = Image::get_image_required_mipmaps(rt->size.width, rt->size.height, Image::FORMAT_RGBA8); @@ -6131,7 +6542,7 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) { tf.format = rt->color_format; tf.width = rt->size.width; tf.height = rt->size.height; - tf.type = RD::TEXTURE_TYPE_2D; + tf.texture_type = RD::TEXTURE_TYPE_2D; tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; tf.mipmaps = mipmaps_required; @@ -6171,7 +6582,7 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) { } } -RID RasterizerStorageRD::render_target_create() { +RID RendererStorageRD::render_target_create() { RenderTarget render_target; render_target.was_used = false; @@ -6184,11 +6595,11 @@ RID RasterizerStorageRD::render_target_create() { return render_target_owner.make_rid(render_target); } -void RasterizerStorageRD::render_target_set_position(RID p_render_target, int p_x, int p_y) { +void RendererStorageRD::render_target_set_position(RID p_render_target, int p_x, int p_y) { //unused for this render target } -void RasterizerStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height) { +void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); rt->size.x = p_width; @@ -6196,63 +6607,63 @@ void RasterizerStorageRD::render_target_set_size(RID p_render_target, int p_widt _update_render_target(rt); } -RID RasterizerStorageRD::render_target_get_texture(RID p_render_target) { +RID RendererStorageRD::render_target_get_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); return rt->texture; } -void RasterizerStorageRD::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { +void RendererStorageRD::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { } -void RasterizerStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { +void RendererStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); rt->flags[p_flag] = p_value; _update_render_target(rt); } -bool RasterizerStorageRD::render_target_was_used(RID p_render_target) { +bool RendererStorageRD::render_target_was_used(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, false); return rt->was_used; } -void RasterizerStorageRD::render_target_set_as_unused(RID p_render_target) { +void RendererStorageRD::render_target_set_as_unused(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); rt->was_used = false; } -Size2 RasterizerStorageRD::render_target_get_size(RID p_render_target) { +Size2 RendererStorageRD::render_target_get_size(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, Size2()); return rt->size; } -RID RasterizerStorageRD::render_target_get_rd_framebuffer(RID p_render_target) { +RID RendererStorageRD::render_target_get_rd_framebuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); return rt->framebuffer; } -RID RasterizerStorageRD::render_target_get_rd_texture(RID p_render_target) { +RID RendererStorageRD::render_target_get_rd_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); return rt->color; } -RID RasterizerStorageRD::render_target_get_rd_backbuffer(RID p_render_target) { +RID RendererStorageRD::render_target_get_rd_backbuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); return rt->backbuffer; } -RID RasterizerStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) { +RID RendererStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); @@ -6263,32 +6674,32 @@ RID RasterizerStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_rende return rt->backbuffer_fb; } -void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { +void RendererStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); rt->clear_requested = true; rt->clear_color = p_clear_color; } -bool RasterizerStorageRD::render_target_is_clear_requested(RID p_render_target) { +bool RendererStorageRD::render_target_is_clear_requested(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, false); return rt->clear_requested; } -Color RasterizerStorageRD::render_target_get_clear_request_color(RID p_render_target) { +Color RendererStorageRD::render_target_get_clear_request_color(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, Color()); return rt->clear_color; } -void RasterizerStorageRD::render_target_disable_clear_request(RID p_render_target) { +void RendererStorageRD::render_target_disable_clear_request(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); rt->clear_requested = false; } -void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) { +void RendererStorageRD::render_target_do_clear_request(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); if (!rt->clear_requested) { @@ -6301,7 +6712,7 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) { rt->clear_requested = false; } -void RasterizerStorageRD::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) { +void RendererStorageRD::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) { @@ -6314,7 +6725,7 @@ void RasterizerStorageRD::render_target_set_sdf_size_and_scale(RID p_render_targ _render_target_clear_sdf(rt); } -Rect2i RasterizerStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) const { +Rect2i RendererStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) const { Size2i margin; int scale; switch (rt->sdf_oversize) { @@ -6343,14 +6754,14 @@ Rect2i RasterizerStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) return r; } -Rect2i RasterizerStorageRD::render_target_get_sdf_rect(RID p_render_target) const { +Rect2i RendererStorageRD::render_target_get_sdf_rect(RID p_render_target) const { const RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, Rect2i()); return _render_target_get_sdf_rect(rt); } -RID RasterizerStorageRD::render_target_get_sdf_texture(RID p_render_target) { +RID RendererStorageRD::render_target_get_sdf_texture(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); if (rt->sdf_buffer_read.is_null()) { @@ -6360,7 +6771,7 @@ RID RasterizerStorageRD::render_target_get_sdf_texture(RID p_render_target) { tformat.width = 4; tformat.height = 4; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; + tformat.texture_type = RD::TEXTURE_TYPE_2D; Vector<uint8_t> pv; pv.resize(16 * 4); @@ -6373,7 +6784,7 @@ RID RasterizerStorageRD::render_target_get_sdf_texture(RID p_render_target) { return rt->sdf_buffer_read; } -void RasterizerStorageRD::_render_target_allocate_sdf(RenderTarget *rt) { +void RendererStorageRD::_render_target_allocate_sdf(RenderTarget *rt) { ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_valid()); if (rt->sdf_buffer_read.is_valid()) { RD::get_singleton()->free(rt->sdf_buffer_read); @@ -6387,7 +6798,7 @@ void RasterizerStorageRD::_render_target_allocate_sdf(RenderTarget *rt) { tformat.width = size.width; tformat.height = size.height; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; + tformat.texture_type = RD::TEXTURE_TYPE_2D; rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView()); @@ -6434,28 +6845,28 @@ void RasterizerStorageRD::_render_target_allocate_sdf(RenderTarget *rt) { Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 1; u.ids.push_back(rt->sdf_buffer_write); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 2; u.ids.push_back(rt->sdf_buffer_read); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 3; u.ids.push_back(rt->sdf_buffer_process[0]); uniforms.push_back(u); } { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 4; u.ids.push_back(rt->sdf_buffer_process[1]); uniforms.push_back(u); @@ -6467,7 +6878,7 @@ void RasterizerStorageRD::_render_target_allocate_sdf(RenderTarget *rt) { } } -void RasterizerStorageRD::_render_target_clear_sdf(RenderTarget *rt) { +void RendererStorageRD::_render_target_clear_sdf(RenderTarget *rt) { if (rt->sdf_buffer_read.is_valid()) { RD::get_singleton()->free(rt->sdf_buffer_read); rt->sdf_buffer_read = RID(); @@ -6485,7 +6896,7 @@ void RasterizerStorageRD::_render_target_clear_sdf(RenderTarget *rt) { } } -RID RasterizerStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) { +RID RendererStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); @@ -6495,7 +6906,7 @@ RID RasterizerStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) return rt->sdf_buffer_write_fb; } -void RasterizerStorageRD::render_target_sdf_process(RID p_render_target) { +void RendererStorageRD::render_target_sdf_process(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null()); @@ -6570,7 +6981,7 @@ void RasterizerStorageRD::render_target_sdf_process(RID p_render_target) { RD::get_singleton()->compute_list_end(); } -void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) { +void RendererStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); if (!rt->backbuffer.is_valid()) { @@ -6581,7 +6992,7 @@ void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, if (p_region == Rect2i()) { region.size = rt->size; } else { - region = Rect2i(Size2i(), rt->size).clip(p_region); + region = Rect2i(Size2i(), rt->size).intersection(p_region); if (region.size == Size2i()) { return; //nothing to do } @@ -6610,7 +7021,7 @@ void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, } } -void RasterizerStorageRD::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) { +void RendererStorageRD::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); if (!rt->backbuffer.is_valid()) { @@ -6621,7 +7032,7 @@ void RasterizerStorageRD::render_target_clear_back_buffer(RID p_render_target, c if (p_region == Rect2i()) { region.size = rt->size; } else { - region = Rect2i(Size2i(), rt->size).clip(p_region); + region = Rect2i(Size2i(), rt->size).intersection(p_region); if (region.size == Size2i()) { return; //nothing to do } @@ -6631,7 +7042,7 @@ void RasterizerStorageRD::render_target_clear_back_buffer(RID p_render_target, c effects.set_color(rt->backbuffer_mipmap0, p_color, region, true); } -void RasterizerStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { +void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); if (!rt->backbuffer.is_valid()) { @@ -6642,7 +7053,7 @@ void RasterizerStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_tar if (p_region == Rect2i()) { region.size = rt->size; } else { - region = Rect2i(Size2i(), rt->size).clip(p_region); + region = Rect2i(Size2i(), rt->size).intersection(p_region); if (region.size == Size2i()) { return; //nothing to do } @@ -6663,70 +7074,70 @@ void RasterizerStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_tar } } -RID RasterizerStorageRD::render_target_get_framebuffer_uniform_set(RID p_render_target) { +RID RendererStorageRD::render_target_get_framebuffer_uniform_set(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); return rt->framebuffer_uniform_set; } -RID RasterizerStorageRD::render_target_get_backbuffer_uniform_set(RID p_render_target) { +RID RendererStorageRD::render_target_get_backbuffer_uniform_set(RID p_render_target) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND_V(!rt, RID()); return rt->backbuffer_uniform_set; } -void RasterizerStorageRD::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) { +void RendererStorageRD::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); rt->framebuffer_uniform_set = p_uniform_set; } -void RasterizerStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) { +void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); rt->backbuffer_uniform_set = p_uniform_set; } -void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) { +void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) { if (mesh_owner.owns(p_base)) { Mesh *mesh = mesh_owner.getornull(p_base); - p_instance->update_dependency(&mesh->instance_dependency); + p_instance->update_dependency(&mesh->dependency); } else if (multimesh_owner.owns(p_base)) { MultiMesh *multimesh = multimesh_owner.getornull(p_base); - p_instance->update_dependency(&multimesh->instance_dependency); + p_instance->update_dependency(&multimesh->dependency); if (multimesh->mesh.is_valid()) { base_update_dependency(multimesh->mesh, p_instance); } } else if (reflection_probe_owner.owns(p_base)) { ReflectionProbe *rp = reflection_probe_owner.getornull(p_base); - p_instance->update_dependency(&rp->instance_dependency); + p_instance->update_dependency(&rp->dependency); } else if (decal_owner.owns(p_base)) { Decal *decal = decal_owner.getornull(p_base); - p_instance->update_dependency(&decal->instance_dependency); + p_instance->update_dependency(&decal->dependency); } else if (gi_probe_owner.owns(p_base)) { GIProbe *gip = gi_probe_owner.getornull(p_base); - p_instance->update_dependency(&gip->instance_dependency); + p_instance->update_dependency(&gip->dependency); } else if (lightmap_owner.owns(p_base)) { Lightmap *lm = lightmap_owner.getornull(p_base); - p_instance->update_dependency(&lm->instance_dependency); + p_instance->update_dependency(&lm->dependency); } else if (light_owner.owns(p_base)) { Light *l = light_owner.getornull(p_base); - p_instance->update_dependency(&l->instance_dependency); + p_instance->update_dependency(&l->dependency); } else if (particles_owner.owns(p_base)) { Particles *p = particles_owner.getornull(p_base); - p_instance->update_dependency(&p->instance_dependency); + p_instance->update_dependency(&p->dependency); } else if (particles_collision_owner.owns(p_base)) { ParticlesCollision *pc = particles_collision_owner.getornull(p_base); - p_instance->update_dependency(&pc->instance_dependency); + p_instance->update_dependency(&pc->dependency); } } -void RasterizerStorageRD::skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { +void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND(!skeleton); - p_instance->update_dependency(&skeleton->instance_dependency); + p_instance->update_dependency(&skeleton->dependency); } -RS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const { +RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { if (mesh_owner.owns(p_rid)) { return RS::INSTANCE_MESH; } @@ -6758,7 +7169,7 @@ RS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const { return RS::INSTANCE_NONE; } -void RasterizerStorageRD::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) { +void RendererStorageRD::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) { if (!decal_atlas.textures.has(p_texture)) { DecalAtlas::Texture t; t.users = 1; @@ -6774,7 +7185,7 @@ void RasterizerStorageRD::texture_add_to_decal_atlas(RID p_texture, bool p_panor } } -void RasterizerStorageRD::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) { +void RendererStorageRD::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) { DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture); ERR_FAIL_COND(!t); t->users--; @@ -6788,15 +7199,15 @@ void RasterizerStorageRD::texture_remove_from_decal_atlas(RID p_texture, bool p_ } } -RID RasterizerStorageRD::decal_atlas_get_texture() const { +RID RendererStorageRD::decal_atlas_get_texture() const { return decal_atlas.texture; } -RID RasterizerStorageRD::decal_atlas_get_texture_srgb() const { +RID RendererStorageRD::decal_atlas_get_texture_srgb() const { return decal_atlas.texture_srgb; } -void RasterizerStorageRD::_update_decal_atlas() { +void RendererStorageRD::_update_decal_atlas() { if (!decal_atlas.dirty) { return; //nothing to do } @@ -6923,7 +7334,7 @@ void RasterizerStorageRD::_update_decal_atlas() { tformat.width = decal_atlas.size.width; tformat.height = decal_atlas.size.height; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; + tformat.texture_type = RD::TEXTURE_TYPE_2D; tformat.mipmaps = decal_atlas.mipmaps; tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM); tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB); @@ -6988,7 +7399,7 @@ void RasterizerStorageRD::_update_decal_atlas() { } } -int32_t RasterizerStorageRD::_global_variable_allocate(uint32_t p_elements) { +int32_t RendererStorageRD::_global_variable_allocate(uint32_t p_elements) { int32_t idx = 0; while (idx + p_elements <= global_variables.buffer_size) { if (global_variables.buffer_usage[idx].elements == 0) { @@ -7014,7 +7425,7 @@ int32_t RasterizerStorageRD::_global_variable_allocate(uint32_t p_elements) { return -1; } -void RasterizerStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { +void RendererStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) { switch (p_type) { case RS::GLOBAL_VAR_TYPE_BOOL: { GlobalVariables::Value &bv = global_variables.buffer_values[p_index]; @@ -7291,7 +7702,7 @@ void RasterizerStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS:: } } -void RasterizerStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { +void RendererStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) { int32_t prev_chunk = -1; for (int32_t i = 0; i < p_elements; i++) { @@ -7307,7 +7718,7 @@ void RasterizerStorageRD::_global_variable_mark_buffer_dirty(int32_t p_index, in } } -void RasterizerStorageRD::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { +void RendererStorageRD::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) { ERR_FAIL_COND(global_variables.variables.has(p_name)); GlobalVariables::Variable gv; gv.type = p_type; @@ -7345,7 +7756,7 @@ void RasterizerStorageRD::global_variable_add(const StringName &p_name, RS::Glob global_variables.variables[p_name] = gv; } -void RasterizerStorageRD::global_variable_remove(const StringName &p_name) { +void RendererStorageRD::global_variable_remove(const StringName &p_name) { if (!global_variables.variables.has(p_name)) { return; } @@ -7361,7 +7772,7 @@ void RasterizerStorageRD::global_variable_remove(const StringName &p_name) { global_variables.variables.erase(p_name); } -Vector<StringName> RasterizerStorageRD::global_variable_get_list() const { +Vector<StringName> RendererStorageRD::global_variable_get_list() const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); } @@ -7375,7 +7786,7 @@ Vector<StringName> RasterizerStorageRD::global_variable_get_list() const { return names; } -void RasterizerStorageRD::global_variable_set(const StringName &p_name, const Variant &p_value) { +void RendererStorageRD::global_variable_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_COND(!global_variables.variables.has(p_name)); GlobalVariables::Variable &gv = global_variables.variables[p_name]; gv.value = p_value; @@ -7395,7 +7806,7 @@ void RasterizerStorageRD::global_variable_set(const StringName &p_name, const Va } } -void RasterizerStorageRD::global_variable_set_override(const StringName &p_name, const Variant &p_value) { +void RendererStorageRD::global_variable_set_override(const StringName &p_name, const Variant &p_value) { if (!global_variables.variables.has(p_name)) { return; //variable may not exist } @@ -7423,7 +7834,7 @@ void RasterizerStorageRD::global_variable_set_override(const StringName &p_name, } } -Variant RasterizerStorageRD::global_variable_get(const StringName &p_name) const { +Variant RendererStorageRD::global_variable_get(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); } @@ -7435,7 +7846,7 @@ Variant RasterizerStorageRD::global_variable_get(const StringName &p_name) const return global_variables.variables[p_name].value; } -RS::GlobalVariableType RasterizerStorageRD::global_variable_get_type_internal(const StringName &p_name) const { +RS::GlobalVariableType RendererStorageRD::global_variable_get_type_internal(const StringName &p_name) const { if (!global_variables.variables.has(p_name)) { return RS::GLOBAL_VAR_TYPE_MAX; } @@ -7443,7 +7854,7 @@ RS::GlobalVariableType RasterizerStorageRD::global_variable_get_type_internal(co return global_variables.variables[p_name].type; } -RS::GlobalVariableType RasterizerStorageRD::global_variable_get_type(const StringName &p_name) const { +RS::GlobalVariableType RendererStorageRD::global_variable_get_type(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); } @@ -7451,7 +7862,7 @@ RS::GlobalVariableType RasterizerStorageRD::global_variable_get_type(const Strin return global_variable_get_type_internal(p_name); } -void RasterizerStorageRD::global_variables_load_settings(bool p_load_textures) { +void RendererStorageRD::global_variables_load_settings(bool p_load_textures) { List<PropertyInfo> settings; ProjectSettings::get_singleton()->get_property_list(&settings); @@ -7532,15 +7943,15 @@ void RasterizerStorageRD::global_variables_load_settings(bool p_load_textures) { } } -void RasterizerStorageRD::global_variables_clear() { +void RendererStorageRD::global_variables_clear() { global_variables.variables.clear(); //not right but for now enough } -RID RasterizerStorageRD::global_variables_get_storage_buffer() const { +RID RendererStorageRD::global_variables_get_storage_buffer() const { return global_variables.buffer; } -int32_t RasterizerStorageRD::global_variables_instance_allocate(RID p_instance) { +int32_t RendererStorageRD::global_variables_instance_allocate(RID p_instance) { ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1); int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); global_variables.instance_buffer_pos[p_instance] = pos; //save anyway @@ -7549,7 +7960,7 @@ int32_t RasterizerStorageRD::global_variables_instance_allocate(RID p_instance) return pos; } -void RasterizerStorageRD::global_variables_instance_free(RID p_instance) { +void RendererStorageRD::global_variables_instance_free(RID p_instance) { ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance)); int32_t pos = global_variables.instance_buffer_pos[p_instance]; if (pos >= 0) { @@ -7558,7 +7969,7 @@ void RasterizerStorageRD::global_variables_instance_free(RID p_instance) { global_variables.instance_buffer_pos.erase(p_instance); } -void RasterizerStorageRD::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { +void RendererStorageRD::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) { if (!global_variables.instance_buffer_pos.has(p_instance)) { return; //just not allocated, ignore } @@ -7601,7 +8012,7 @@ void RasterizerStorageRD::global_variables_instance_update(RID p_instance, int p _global_variable_mark_buffer_dirty(pos, 1); } -void RasterizerStorageRD::_update_global_variables() { +void RendererStorageRD::_update_global_variables() { if (global_variables.buffer_dirty_region_count > 0) { uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE; if (total_regions / global_variables.buffer_dirty_region_count <= 4) { @@ -7651,7 +8062,7 @@ void RasterizerStorageRD::_update_global_variables() { } } -void RasterizerStorageRD::update_dirty_resources() { +void RendererStorageRD::update_dirty_resources() { _update_global_variables(); //must do before materials, so it can queue them for update _update_queued_materials(); _update_dirty_multimeshes(); @@ -7659,7 +8070,7 @@ void RasterizerStorageRD::update_dirty_resources() { _update_decal_atlas(); } -bool RasterizerStorageRD::has_os_feature(const String &p_feature) const { +bool RendererStorageRD::has_os_feature(const String &p_feature) const { if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { return true; } @@ -7683,7 +8094,7 @@ bool RasterizerStorageRD::has_os_feature(const String &p_feature) const { return false; } -bool RasterizerStorageRD::free(RID p_rid) { +bool RendererStorageRD::free(RID p_rid) { if (texture_owner.owns(p_rid)) { Texture *t = texture_owner.getornull(p_rid); @@ -7744,28 +8155,40 @@ bool RasterizerStorageRD::free(RID p_rid) { _update_queued_materials(); } material_set_shader(p_rid, RID()); //clean up shader - material->instance_dependency.instance_notify_deleted(p_rid); + material->dependency.deleted_notify(p_rid); + material_owner.free(p_rid); } else if (mesh_owner.owns(p_rid)) { mesh_clear(p_rid); Mesh *mesh = mesh_owner.getornull(p_rid); - mesh->instance_dependency.instance_notify_deleted(p_rid); + mesh->dependency.deleted_notify(p_rid); + if (mesh->instances.size()) { + ERR_PRINT("deleting mesh with active instances"); + } mesh_owner.free(p_rid); + } else if (mesh_instance_owner.owns(p_rid)) { + MeshInstance *mi = mesh_instance_owner.getornull(p_rid); + _mesh_instance_clear(mi); + mi->mesh->instances.erase(mi->I); + mi->I = nullptr; + mesh_instance_owner.free(p_rid); + memdelete(mi); + } else if (multimesh_owner.owns(p_rid)) { _update_dirty_multimeshes(); multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D); MultiMesh *multimesh = multimesh_owner.getornull(p_rid); - multimesh->instance_dependency.instance_notify_deleted(p_rid); + multimesh->dependency.deleted_notify(p_rid); multimesh_owner.free(p_rid); } else if (skeleton_owner.owns(p_rid)) { _update_dirty_skeletons(); skeleton_allocate(p_rid, 0); Skeleton *skeleton = skeleton_owner.getornull(p_rid); - skeleton->instance_dependency.instance_notify_deleted(p_rid); + skeleton->dependency.deleted_notify(p_rid); skeleton_owner.free(p_rid); } else if (reflection_probe_owner.owns(p_rid)) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid); - reflection_probe->instance_dependency.instance_notify_deleted(p_rid); + reflection_probe->dependency.deleted_notify(p_rid); reflection_probe_owner.free(p_rid); } else if (decal_owner.owns(p_rid)) { Decal *decal = decal_owner.getornull(p_rid); @@ -7774,30 +8197,30 @@ bool RasterizerStorageRD::free(RID p_rid) { texture_remove_from_decal_atlas(decal->textures[i]); } } - decal->instance_dependency.instance_notify_deleted(p_rid); + decal->dependency.deleted_notify(p_rid); decal_owner.free(p_rid); } else if (gi_probe_owner.owns(p_rid)) { gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate GIProbe *gi_probe = gi_probe_owner.getornull(p_rid); - gi_probe->instance_dependency.instance_notify_deleted(p_rid); + gi_probe->dependency.deleted_notify(p_rid); gi_probe_owner.free(p_rid); } else if (lightmap_owner.owns(p_rid)) { lightmap_set_textures(p_rid, RID(), false); Lightmap *lightmap = lightmap_owner.getornull(p_rid); - lightmap->instance_dependency.instance_notify_deleted(p_rid); + lightmap->dependency.deleted_notify(p_rid); lightmap_owner.free(p_rid); } else if (light_owner.owns(p_rid)) { light_set_projector(p_rid, RID()); //clear projector // delete the texture Light *light = light_owner.getornull(p_rid); - light->instance_dependency.instance_notify_deleted(p_rid); + light->dependency.deleted_notify(p_rid); light_owner.free(p_rid); } else if (particles_owner.owns(p_rid)) { Particles *particles = particles_owner.getornull(p_rid); _particles_free_data(particles); - particles->instance_dependency.instance_notify_deleted(p_rid); + particles->dependency.deleted_notify(p_rid); particles_owner.free(p_rid); } else if (particles_collision_owner.owns(p_rid)) { ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_rid); @@ -7805,8 +8228,10 @@ bool RasterizerStorageRD::free(RID p_rid) { if (particles_collision->heightfield_texture.is_valid()) { RD::get_singleton()->free(particles_collision->heightfield_texture); } - particles_collision->instance_dependency.instance_notify_deleted(p_rid); + particles_collision->dependency.deleted_notify(p_rid); particles_collision_owner.free(p_rid); + } else if (particles_collision_instance_owner.owns(p_rid)) { + particles_collision_instance_owner.free(p_rid); } else if (render_target_owner.owns(p_rid)) { RenderTarget *rt = render_target_owner.getornull(p_rid); @@ -7826,41 +8251,41 @@ bool RasterizerStorageRD::free(RID p_rid) { return true; } -RasterizerEffectsRD *RasterizerStorageRD::get_effects() { +EffectsRD *RendererStorageRD::get_effects() { return &effects; } -void RasterizerStorageRD::capture_timestamps_begin() { +void RendererStorageRD::capture_timestamps_begin() { RD::get_singleton()->capture_timestamp("Frame Begin", false); } -void RasterizerStorageRD::capture_timestamp(const String &p_name) { +void RendererStorageRD::capture_timestamp(const String &p_name) { RD::get_singleton()->capture_timestamp(p_name, true); } -uint32_t RasterizerStorageRD::get_captured_timestamps_count() const { +uint32_t RendererStorageRD::get_captured_timestamps_count() const { return RD::get_singleton()->get_captured_timestamps_count(); } -uint64_t RasterizerStorageRD::get_captured_timestamps_frame() const { +uint64_t RendererStorageRD::get_captured_timestamps_frame() const { return RD::get_singleton()->get_captured_timestamps_frame(); } -uint64_t RasterizerStorageRD::get_captured_timestamp_gpu_time(uint32_t p_index) const { +uint64_t RendererStorageRD::get_captured_timestamp_gpu_time(uint32_t p_index) const { return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index); } -uint64_t RasterizerStorageRD::get_captured_timestamp_cpu_time(uint32_t p_index) const { +uint64_t RendererStorageRD::get_captured_timestamp_cpu_time(uint32_t p_index) const { return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index); } -String RasterizerStorageRD::get_captured_timestamp_name(uint32_t p_index) const { +String RendererStorageRD::get_captured_timestamp_name(uint32_t p_index) const { return RD::get_singleton()->get_captured_timestamp_name(p_index); } -RasterizerStorageRD *RasterizerStorageRD::base_singleton = nullptr; +RendererStorageRD *RendererStorageRD::base_singleton = nullptr; -RasterizerStorageRD::RasterizerStorageRD() { +RendererStorageRD::RendererStorageRD() { base_singleton = this; for (int i = 0; i < SHADER_TYPE_MAX; i++) { @@ -7886,7 +8311,7 @@ RasterizerStorageRD::RasterizerStorageRD() { tformat.width = 4; tformat.height = 4; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; + tformat.texture_type = RD::TEXTURE_TYPE_2D; Vector<uint8_t> pv; pv.resize(16 * 4); @@ -7978,7 +8403,7 @@ RasterizerStorageRD::RasterizerStorageRD() { tformat.height = 4; tformat.array_layers = 6; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; Vector<uint8_t> pv; pv.resize(16 * 4); @@ -8006,7 +8431,7 @@ RasterizerStorageRD::RasterizerStorageRD() { tformat.height = 4; tformat.array_layers = 6; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_CUBE; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE; Vector<uint8_t> pv; pv.resize(16 * 4); @@ -8034,7 +8459,7 @@ RasterizerStorageRD::RasterizerStorageRD() { tformat.height = 4; tformat.array_layers = 6; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_CUBE; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE; Vector<uint8_t> pv; pv.resize(16 * 4); @@ -8062,7 +8487,7 @@ RasterizerStorageRD::RasterizerStorageRD() { tformat.height = 4; tformat.depth = 4; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_3D; + tformat.texture_type = RD::TEXTURE_TYPE_3D; Vector<uint8_t> pv; pv.resize(64 * 4); @@ -8088,7 +8513,7 @@ RasterizerStorageRD::RasterizerStorageRD() { tformat.height = 4; tformat.array_layers = 1; tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_2D_ARRAY; + tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; Vector<uint8_t> pv; pv.resize(16 * 4); @@ -8249,6 +8674,19 @@ RasterizerStorageRD::RasterizerStorageRD() { mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); } + for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) { + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); + } + { //bones buffer.resize(sizeof(uint32_t) * 4); { @@ -8311,8 +8749,8 @@ RasterizerStorageRD::RasterizerStorageRD() { particles_modes.push_back(""); particles_shader.shader.initialize(particles_modes, String()); } - shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); - material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); + shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs); + material_set_data_request_function(RendererStorageRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs); { ShaderCompilerRD::DefaultIdentifierActions actions; @@ -8342,7 +8780,7 @@ RasterizerStorageRD::RasterizerStorageRD() { actions.renames["RESTART_VELOCITY"] = "restart_velocity"; actions.renames["RESTART_COLOR"] = "restart_color"; actions.renames["RESTART_CUSTOM"] = "restart_custom"; - actions.renames["emit_particle"] = "emit_particle"; + actions.renames["emit_subparticle"] = "emit_subparticle"; actions.renames["COLLIDED"] = "collided"; actions.renames["COLLISION_NORMAL"] = "collision_normal"; actions.renames["COLLISION_DEPTH"] = "collision_depth"; @@ -8373,14 +8811,14 @@ RasterizerStorageRD::RasterizerStorageRD() { particles_shader.default_material = material_create(); material_set_shader(particles_shader.default_material, particles_shader.default_shader); - ParticlesMaterialData *md = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, RasterizerStorageRD::SHADER_TYPE_PARTICLES); + ParticlesMaterialData *md = (ParticlesMaterialData *)material_get_data(particles_shader.default_material, RendererStorageRD::SHADER_TYPE_PARTICLES); particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; u.binding = 1; u.ids.resize(12); RID *ids_ptr = u.ids.ptrw(); @@ -8401,7 +8839,7 @@ RasterizerStorageRD::RasterizerStorageRD() { { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; u.ids.push_back(global_variables_get_storage_buffer()); uniforms.push_back(u); @@ -8444,9 +8882,33 @@ RasterizerStorageRD::RasterizerStorageRD() { rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i)); } } + { + Vector<String> skeleton_modes; + skeleton_modes.push_back("\n#define MODE_2D\n"); + skeleton_modes.push_back(""); + + skeleton_shader.shader.initialize(skeleton_modes); + skeleton_shader.version = skeleton_shader.shader.version_create(); + for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) { + skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i); + skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]); + } + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 0; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(default_rd_storage_buffer); + uniforms.push_back(u); + } + skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON); + } + } } -RasterizerStorageRD::~RasterizerStorageRD() { +RendererStorageRD::~RendererStorageRD() { memdelete_arr(global_variables.buffer_values); memdelete_arr(global_variables.buffer_usage); memdelete_arr(global_variables.buffer_dirty_regions); @@ -8471,6 +8933,9 @@ RasterizerStorageRD::~RasterizerStorageRD() { giprobe_sdf_shader.version_free(giprobe_sdf_shader_version); particles_shader.copy_shader.version_free(particles_shader.copy_shader_version); + rt_sdf.shader.version_free(rt_sdf.shader_version); + + skeleton_shader.shader.version_free(skeleton_shader.version); RenderingServer::get_singleton()->free(particles_shader.default_material); RenderingServer::get_singleton()->free(particles_shader.default_shader); diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 4a708fc94f..5ef73f0db8 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer_storage_rd.h */ +/* renderer_storage_rd.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,20 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RASTERIZER_STORAGE_RD_H -#define RASTERIZER_STORAGE_RD_H +#ifndef RENDERING_SERVER_STORAGE_RD_H +#define RENDERING_SERVER_STORAGE_RD_H +#include "core/templates/list.h" +#include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" -#include "servers/rendering/rasterizer.h" -#include "servers/rendering/rasterizer_rd/rasterizer_effects_rd.h" -#include "servers/rendering/rasterizer_rd/shader_compiler_rd.h" -#include "servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/particles.glsl.gen.h" -#include "servers/rendering/rasterizer_rd/shaders/particles_copy.glsl.gen.h" +#include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_rd/effects_rd.h" +#include "servers/rendering/renderer_rd/shader_compiler_rd.h" +#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" - -class RasterizerStorageRD : public RasterizerStorage { +class RendererStorageRD : public RendererStorage { public: static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) { p_array[0] = p_mtx.basis.elements[0][0]; @@ -124,6 +127,8 @@ public: virtual bool is_animated() const = 0; virtual bool casts_shadows() const = 0; virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; + virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } + virtual ~ShaderData() {} }; @@ -139,7 +144,7 @@ public: virtual ~MaterialData(); private: - friend class RasterizerStorageRD; + friend class RendererStorageRD; RID self; List<RID>::Element *global_buffer_E = nullptr; List<RID>::Element *global_texture_E = nullptr; @@ -170,6 +175,10 @@ public: DEFAULT_RD_BUFFER_COLOR, DEFAULT_RD_BUFFER_TEX_UV, DEFAULT_RD_BUFFER_TEX_UV2, + DEFAULT_RD_BUFFER_CUSTOM0, + DEFAULT_RD_BUFFER_CUSTOM1, + DEFAULT_RD_BUFFER_CUSTOM2, + DEFAULT_RD_BUFFER_CUSTOM3, DEFAULT_RD_BUFFER_BONES, DEFAULT_RD_BUFFER_WEIGHTS, DEFAULT_RD_BUFFER_MAX, @@ -180,7 +189,7 @@ private: struct CanvasTexture { RID diffuse; - RID normalmap; + RID normal_map; RID specular; Color specular_color = Color(1, 1, 1, 1); float shininess = 1.0; @@ -353,6 +362,7 @@ private: Shader *shader; //shortcut to shader data and type ShaderType shader_type; + uint32_t shader_id = 0; bool update_requested; bool uniform_dirty; bool texture_dirty; @@ -360,7 +370,7 @@ private: Map<StringName, Variant> params; int32_t priority; RID next_pass; - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; }; MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; @@ -372,13 +382,19 @@ private: /* Mesh */ + struct MeshInstance; + struct Mesh { struct Surface { RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS; uint32_t format = 0; RID vertex_buffer; + RID attribute_buffer; + RID skin_buffer; uint32_t vertex_count = 0; + uint32_t vertex_buffer_size = 0; + uint32_t skin_buffer_size = 0; // A different pipeline needs to be allocated // depending on the inputs available in the @@ -414,8 +430,7 @@ private: Vector<AABB> bone_aabbs; - Vector<RID> blend_shapes; - RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed + RID blend_shape_buffer; RID material; @@ -427,6 +442,8 @@ private: uint32_t particles_render_index = 0; uint64_t particles_render_pass = 0; + + RID uniform_set; }; uint32_t blend_shape_count = 0; @@ -437,17 +454,90 @@ private: Vector<AABB> bone_aabbs; + bool has_bone_weights = false; + AABB aabb; AABB custom_aabb; Vector<RID> material_cache; - RasterizerScene::InstanceDependency instance_dependency; + List<MeshInstance *> instances; + + Dependency dependency; }; mutable RID_Owner<Mesh> mesh_owner; - void _mesh_surface_generate_version_for_input_mask(Mesh::Surface *s, uint32_t p_input_mask); + struct MeshInstance { + Mesh *mesh; + RID skeleton; + struct Surface { + RID vertex_buffer; + RID uniform_set; + + Mesh::Surface::Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; + }; + LocalVector<Surface> surfaces; + LocalVector<float> blend_weights; + + RID blend_weights_buffer; + List<MeshInstance *>::Element *I = nullptr; //used to erase itself + uint64_t skeleton_version = 0; + bool dirty = false; + bool weights_dirty = false; + SelfList<MeshInstance> weight_update_list; + SelfList<MeshInstance> array_update_list; + MeshInstance() : + weight_update_list(this), array_update_list(this) {} + }; + + void _mesh_instance_clear(MeshInstance *mi); + void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface); + + mutable RID_PtrOwner<MeshInstance> mesh_instance_owner; + + SelfList<MeshInstance>::List dirty_mesh_instance_weights; + SelfList<MeshInstance>::List dirty_mesh_instance_arrays; + + struct SkeletonShader { + struct PushConstant { + uint32_t has_normal; + uint32_t has_tangent; + uint32_t has_skeleton; + uint32_t has_blend_shape; + + uint32_t vertex_count; + uint32_t vertex_stride; + uint32_t skin_stride; + uint32_t skin_weight_offset; + + uint32_t blend_shape_count; + uint32_t normalized_blend_shapes; + uint32_t pad0; + uint32_t pad1; + }; + + enum { + UNIFORM_SET_INSTANCE = 0, + UNIFORM_SET_SURFACE = 1, + UNIFORM_SET_SKELETON = 2, + }; + enum { + SHADER_MODE_2D, + SHADER_MODE_3D, + SHADER_MODE_MAX + }; + + SkeletonShaderRD shader; + RID version; + RID version_shader[SHADER_MODE_MAX]; + RID pipeline[SHADER_MODE_MAX]; + + RID default_skeleton_uniform_set; + } skeleton_shader; + + void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr); RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; @@ -476,7 +566,7 @@ private: bool dirty = false; MultiMesh *dirty_list = nullptr; - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; }; mutable RID_Owner<MultiMesh> multimesh_owner; @@ -647,7 +737,7 @@ private: ParticleEmissionBuffer *emission_buffer = nullptr; RID emission_storage_buffer; - Set<RasterizerScene::InstanceBase *> collisions; + Set<RID> collisions; Particles() : inactive(true), @@ -674,7 +764,7 @@ private: clear(true) { } - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; ParticlesFrameParams frame_params; }; @@ -729,7 +819,7 @@ private: bool valid; RID version; - //RenderPipelineVertexFormatCacheRD pipelines[SKY_VERSION_MAX]; + //PipelineCacheRD pipelines[SKY_VERSION_MAX]; Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms; @@ -747,17 +837,19 @@ private: virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture); virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RasterizerStorage::InstanceShaderParam> *p_param_list) const; + virtual void get_instance_param_list(List<RendererStorage::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; + ParticlesShaderData(); virtual ~ParticlesShaderData(); }; ShaderData *_create_particles_shader_func(); - static RasterizerStorageRD::ShaderData *_create_particles_shader_funcs() { + static RendererStorageRD::ShaderData *_create_particles_shader_funcs() { return base_singleton->_create_particles_shader_func(); } @@ -777,7 +869,7 @@ private: }; MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); - static RasterizerStorageRD::MaterialData *_create_particles_material_funcs(ShaderData *p_shader) { + static RendererStorageRD::MaterialData *_create_particles_material_funcs(ShaderData *p_shader) { return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader)); } @@ -802,11 +894,19 @@ private: RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; }; mutable RID_Owner<ParticlesCollision> particles_collision_owner; + struct ParticlesCollisionInstance { + RID collision; + Transform transform; + bool active = false; + }; + + mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner; + /* Skeleton */ struct Skeleton { @@ -820,8 +920,11 @@ private: Transform2D base_transform_2d; RID uniform_set_3d; + RID uniform_set_mi; - RasterizerScene::InstanceDependency instance_dependency; + uint64_t version = 1; + + Dependency dependency; }; mutable RID_Owner<Skeleton> skeleton_owner; @@ -850,9 +953,10 @@ private: RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; RS::LightDirectionalShadowDepthRangeMode directional_range_mode = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; bool directional_blend_splits = false; + bool directional_sky_only = false; uint64_t version = 0; - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; }; mutable RID_Owner<Light> light_owner; @@ -873,8 +977,9 @@ private: bool box_projection = false; bool enable_shadows = false; uint32_t cull_mask = (1 << 20) - 1; + float lod_threshold = 0.01; - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; }; mutable RID_Owner<ReflectionProbe> reflection_probe_owner; @@ -895,7 +1000,7 @@ private: float distance_fade_length = 1; float normal_fade = 0.0; - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; }; mutable RID_Owner<Decal> decal_owner; @@ -933,7 +1038,7 @@ private: uint32_t version = 1; uint32_t data_version = 1; - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; }; GiprobeSdfShaderRD giprobe_sdf_shader; @@ -962,7 +1067,7 @@ private: int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; }; - RasterizerScene::InstanceDependency instance_dependency; + Dependency dependency; }; bool using_lightmap_array; //high end uses this @@ -1123,7 +1228,7 @@ private: void _update_global_variables(); /* EFFECTS */ - RasterizerEffectsRD effects; + EffectsRD effects; public: /* TEXTURE API */ @@ -1238,6 +1343,8 @@ public: Variant shader_get_param_default(RID p_shader, const StringName &p_param) const; void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const; + /* COMMON MATERIAL API */ RID material_create(); @@ -1255,11 +1362,16 @@ public: void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters); - void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance); + void material_update_dependency(RID p_material, DependencyTracker *p_instance); void material_force_update_textures(RID p_material, ShaderType p_shader_type); void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); + _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) { + Material *material = material_owner.getornull(p_material); + return material->shader_id; + } + _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { Material *material = material_owner.getornull(p_material); if (!material || material->shader_type != p_shader_type) { @@ -1273,6 +1385,8 @@ public: virtual RID mesh_create(); + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count); + /// Return stride virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface); @@ -1297,6 +1411,16 @@ public: virtual void mesh_clear(RID p_mesh); + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton); + + /* MESH INSTANCE */ + + virtual RID mesh_instance_create(RID p_base); + virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton); + virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight); + virtual void mesh_instance_check_for_update(RID p_mesh_instance); + virtual void update_mesh_instances(); + _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!mesh, nullptr); @@ -1304,7 +1428,7 @@ public: if (r_surface_count == 0) { return nullptr; } - if (mesh->material_cache.empty()) { + if (mesh->material_cache.is_empty()) { mesh->material_cache.resize(mesh->surface_count); for (uint32_t i = 0; i < r_surface_count; i++) { mesh->material_cache.write[i] = mesh->surfaces[i]->material; @@ -1314,22 +1438,50 @@ public: return mesh->material_cache.ptr(); } - _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(RID p_mesh, uint32_t p_surface_index) { + _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) { Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, RS::PRIMITIVE_MAX); - ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, RS::PRIMITIVE_MAX); + ERR_FAIL_COND_V(!mesh, nullptr); + ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr); - return mesh->surfaces[p_surface_index]->primitive; + return mesh->surfaces[p_surface_index]; } - _FORCE_INLINE_ void mesh_surface_get_arrays_and_format(RID p_mesh, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RID &r_index_array_rd, RD::VertexFormatID &r_vertex_format) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); + _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) { + Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface); + return surface->primitive; + } - Mesh::Surface *s = mesh->surfaces[p_surface_index]; + _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + return s->lod_count > 0; + } + + _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + return s->index_array; + } + + _FORCE_INLINE_ RID mesh_surface_get_index_array_with_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_lod_threshold) const { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); + + int32_t current_lod = -1; + for (uint32_t i = 0; i < s->lod_count; i++) { + float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold; + if (screen_size > p_lod_threshold) { + break; + } + current_lod = i; + } + if (current_lod == -1) { + return s->index_array; + } else { + return s->lods[current_lod].index_array; + } + } - r_index_array_rd = s->index_array; + _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); s->version_lock.lock(); @@ -1346,9 +1498,11 @@ public: return; } - uint32_t version = s->version_count; //gets added at the end + uint32_t version = s->version_count; + s->version_count++; + s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); - _mesh_surface_generate_version_for_input_mask(s, p_input_mask); + _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask); r_vertex_format = s->versions[version].vertex_format; r_vertex_array_rd = s->versions[version].vertex_array; @@ -1356,6 +1510,42 @@ public: s->version_lock.unlock(); } + _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) { + MeshInstance *mi = mesh_instance_owner.getornull(p_mesh_instance); + ERR_FAIL_COND(!mi); + Mesh *mesh = mi->mesh; + ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); + + MeshInstance::Surface *mis = &mi->surfaces[p_surface_index]; + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + s->version_lock.lock(); + + //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way + + for (uint32_t i = 0; i < mis->version_count; i++) { + if (mis->versions[i].input_mask != p_input_mask) { + continue; + } + //we have this version, hooray + r_vertex_format = mis->versions[i].vertex_format; + r_vertex_array_rd = mis->versions[i].vertex_array; + s->version_lock.unlock(); + return; + } + + uint32_t version = mis->version_count; + mis->version_count++; + mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count); + + _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis); + + r_vertex_format = mis->versions[version].vertex_format; + r_vertex_array_rd = mis->versions[version].vertex_array; + + s->version_lock.unlock(); + } + _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) { ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID()); return mesh_default_rd_buffers[p_buffer]; @@ -1456,7 +1646,7 @@ public: if (!multimesh->uniform_set_3d.is_valid()) { Vector<RD::Uniform> uniforms; RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; u.ids.push_back(multimesh->buffer); uniforms.push_back(u); @@ -1494,6 +1684,10 @@ public: void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; + _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) { + return skeleton_owner.getornull(p_skeleton) != nullptr; + } + _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); ERR_FAIL_COND_V(!skeleton, RID()); @@ -1504,7 +1698,7 @@ public: if (!skeleton->uniform_set_3d.is_valid()) { Vector<RD::Uniform> uniforms; RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; u.ids.push_back(skeleton->buffer); uniforms.push_back(u); @@ -1537,6 +1731,8 @@ public: void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode); void light_directional_set_blend_splits(RID p_light, bool p_enable); bool light_directional_get_blend_splits(RID p_light) const; + void light_directional_set_sky_only(RID p_light, bool p_sky_only); + bool light_directional_is_sky_only(RID p_light) const; void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode); RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const; @@ -1635,6 +1831,7 @@ public: void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable); void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers); void reflection_probe_set_resolution(RID p_probe, int p_resolution); + void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio); AABB reflection_probe_get_aabb(RID p_probe) const; RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; @@ -1642,6 +1839,8 @@ public: Vector3 reflection_probe_get_extents(RID p_probe) const; Vector3 reflection_probe_get_origin_offset(RID p_probe) const; float reflection_probe_get_origin_max_distance(RID p_probe) const; + float reflection_probe_get_lod_threshold(RID p_probe) const; + int reflection_probe_get_resolution(RID p_probe) const; bool reflection_probe_renders_shadows(RID p_probe) const; @@ -1652,8 +1851,8 @@ public: Color reflection_probe_get_ambient_color(RID p_probe) const; float reflection_probe_get_ambient_color_energy(RID p_probe) const; - void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance); - void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); + void base_update_dependency(RID p_base, DependencyTracker *p_instance); + void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance); /* DECAL API */ @@ -1802,7 +2001,11 @@ public: _FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const { return lightmap_probe_capture_update_speed; } - + _FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const { + const Lightmap *lm = lightmap_owner.getornull(p_lightmap); + ERR_FAIL_COND_V(!lm, RID()); + return lm->light_texture; + } _FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const { ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays const Lightmap *lm = lightmap_owner.getornull(p_lightmap); @@ -1891,7 +2094,7 @@ public: { RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 0; u.ids.push_back(particles->particle_instance_buffer); uniforms.push_back(u); @@ -1903,8 +2106,8 @@ public: return particles->particles_transforms_buffer_uniform_set; } - virtual void particles_add_collision(RID p_particles, RasterizerScene::InstanceBase *p_instance); - virtual void particles_remove_collision(RID p_particles, RasterizerScene::InstanceBase *p_instance); + virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance); + virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance); /* PARTICLES COLLISION */ @@ -1924,6 +2127,11 @@ public: virtual bool particles_collision_is_heightfield(RID p_particles_collision) const; RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const; + //used from 2D and 3D + virtual RID particles_collision_instance_create(RID p_collision); + virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform); + virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active); + /* GLOBAL VARIABLES API */ virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value); @@ -2013,12 +2221,12 @@ public: RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; } - static RasterizerStorageRD *base_singleton; + static RendererStorageRD *base_singleton; - RasterizerEffectsRD *get_effects(); + EffectsRD *get_effects(); - RasterizerStorageRD(); - ~RasterizerStorageRD(); + RendererStorageRD(); + ~RendererStorageRD(); }; #endif // RASTERIZER_STORAGE_RD_H diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index df5513435a..e77141b26c 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -32,7 +32,7 @@ #include "core/config/project_settings.h" #include "core/os/os.h" -#include "rasterizer_storage_rd.h" +#include "renderer_storage_rd.h" #include "servers/rendering_server.h" #define SL ShaderLanguage @@ -920,7 +920,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge if (adnode->datatype == SL::TYPE_STRUCT) { declaration += _mkid(adnode->struct_name); } else { - declaration = _prestr(adnode->precision) + _typestr(adnode->datatype); + declaration += _prestr(adnode->precision) + _typestr(adnode->datatype); } for (int i = 0; i < adnode->declarations.size(); i++) { if (i > 0) { @@ -930,7 +930,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } declaration += _mkid(adnode->declarations[i].name); declaration += "["; - declaration += itos(adnode->declarations[i].size); + if (adnode->size_expression != nullptr) { + declaration += _dump_node_code(adnode->size_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } else { + declaration += itos(adnode->declarations[i].size); + } declaration += "]"; int sz = adnode->declarations[i].initializer.size(); if (sz > 0) { @@ -986,12 +990,13 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge if (anode->call_expression != nullptr) { code += "."; code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false); - } - - if (anode->index_expression != nullptr) { + } else if (anode->index_expression != nullptr) { code += "["; code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); code += "]"; + } else if (anode->assign_expression != nullptr) { + code += "="; + code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false); } if (anode->name == time_name) { @@ -1229,8 +1234,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge code += "["; code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); code += "]"; + } else if (mnode->assign_expression != nullptr) { + code += "="; + code += _dump_node_code(mnode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false); } - } break; } @@ -1238,7 +1245,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } ShaderLanguage::DataType ShaderCompilerRD::_get_variable_type(const StringName &p_type) { - RS::GlobalVariableType gvt = ((RasterizerStorageRD *)(RasterizerStorage::base_singleton))->global_variable_get_type_internal(p_type); + RS::GlobalVariableType gvt = ((RendererStorageRD *)(RendererStorage::base_singleton))->global_variable_get_type_internal(p_type); return RS::global_variable_type_get_shader_datatype(gvt); } @@ -1333,8 +1340,8 @@ ShaderCompilerRD::ShaderCompilerRD() { actions[RS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; actions[RS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; - actions[RS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap"; - actions[RS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth"; + actions[RS::SHADER_SPATIAL].renames["NORMAL_MAP"] = "normal_map"; + actions[RS::SHADER_SPATIAL].renames["NORMAL_MAP_DEPTH"] = "normal_map_depth"; actions[RS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; actions[RS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; actions[RS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; @@ -1380,8 +1387,8 @@ ShaderCompilerRD::ShaderCompilerRD() { actions[RS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; actions[RS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; actions[RS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; - actions[RS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; - actions[RS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; + actions[RS::SHADER_SPATIAL].usage_defines["NORMAL_MAP"] = "#define ENABLE_NORMAL_MAP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP"; actions[RS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; actions[RS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; actions[RS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.h b/servers/rendering/renderer_rd/shader_compiler_rd.h index 694f8fff91..d127d8e01c 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.h +++ b/servers/rendering/renderer_rd/shader_compiler_rd.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ diff --git a/servers/rendering/rasterizer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 865a1e1bbe..2ae22a8a38 100644 --- a/servers/rendering/rasterizer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -31,7 +31,7 @@ #include "shader_rd.h" #include "core/string/string_builder.h" -#include "rasterizer_rd.h" +#include "renderer_compositor_rd.h" #include "servers/rendering/rendering_device.h" void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name) { @@ -199,6 +199,10 @@ void ShaderRD::_clear_version(Version *p_version) { } void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { + if (!variants_enabled[p_variant]) { + return; //variant is disabled, return + } + Vector<RD::ShaderStageData> stages; String error; @@ -347,6 +351,127 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { } } +RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_version) { + Version *version = version_owner.getornull(p_version); + RS::ShaderNativeSourceCode source_code; + ERR_FAIL_COND_V(!version, source_code); + + source_code.versions.resize(variant_defines.size()); + + for (int i = 0; i < source_code.versions.size(); i++) { + if (!is_compute) { + //vertex stage + + StringBuilder builder; + + builder.append(vertex_codev.get_data()); // version info (if exists) + builder.append("\n"); //make sure defines begin at newline + builder.append(general_defines.get_data()); + builder.append(variant_defines[i].get_data()); + + for (int j = 0; j < version->custom_defines.size(); j++) { + builder.append(version->custom_defines[j].get_data()); + } + + builder.append(vertex_code0.get_data()); //first part of vertex + + builder.append(version->uniforms.get_data()); //uniforms (same for vertex and fragment) + + builder.append(vertex_code1.get_data()); //second part of vertex + + builder.append(version->vertex_globals.get_data()); // vertex globals + + builder.append(vertex_code2.get_data()); //third part of vertex + + builder.append(version->vertex_code.get_data()); // code + + builder.append(vertex_code3.get_data()); //fourth of vertex + + RS::ShaderNativeSourceCode::Version::Stage stage; + stage.name = "vertex"; + stage.code = builder.as_string(); + + source_code.versions.write[i].stages.push_back(stage); + } + + if (!is_compute) { + //fragment stage + + StringBuilder builder; + + builder.append(fragment_codev.get_data()); // version info (if exists) + builder.append("\n"); //make sure defines begin at newline + + builder.append(general_defines.get_data()); + builder.append(variant_defines[i].get_data()); + for (int j = 0; j < version->custom_defines.size(); j++) { + builder.append(version->custom_defines[j].get_data()); + } + + builder.append(fragment_code0.get_data()); //first part of fragment + + builder.append(version->uniforms.get_data()); //uniforms (same for fragment and fragment) + + builder.append(fragment_code1.get_data()); //first part of fragment + + builder.append(version->fragment_globals.get_data()); // fragment globals + + builder.append(fragment_code2.get_data()); //third part of fragment + + builder.append(version->fragment_light.get_data()); // fragment light + + builder.append(fragment_code3.get_data()); //fourth part of fragment + + builder.append(version->fragment_code.get_data()); // fragment code + + builder.append(fragment_code4.get_data()); //fourth part of fragment + + RS::ShaderNativeSourceCode::Version::Stage stage; + stage.name = "fragment"; + stage.code = builder.as_string(); + + source_code.versions.write[i].stages.push_back(stage); + } + + if (is_compute) { + //compute stage + + StringBuilder builder; + + builder.append(compute_codev.get_data()); // version info (if exists) + builder.append("\n"); //make sure defines begin at newline + builder.append(general_defines.get_data()); + builder.append(variant_defines[i].get_data()); + + for (int j = 0; j < version->custom_defines.size(); j++) { + builder.append(version->custom_defines[j].get_data()); + } + + builder.append(compute_code0.get_data()); //first part of compute + + builder.append(version->uniforms.get_data()); //uniforms (same for compute and fragment) + + builder.append(compute_code1.get_data()); //second part of compute + + builder.append(version->compute_globals.get_data()); // compute globals + + builder.append(compute_code2.get_data()); //third part of compute + + builder.append(version->compute_code.get_data()); // code + + builder.append(compute_code3.get_data()); //fourth of compute + + RS::ShaderNativeSourceCode::Version::Stage stage; + stage.name = "compute"; + stage.code = builder.as_string(); + + source_code.versions.write[i].stages.push_back(stage); + } + } + + return source_code; +} + void ShaderRD::_compile_version(Version *p_version) { _clear_version(p_version); @@ -356,7 +481,7 @@ void ShaderRD::_compile_version(Version *p_version) { p_version->variants = memnew_arr(RID, variant_defines.size()); #if 1 - RasterizerRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version); + RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version); #else for (int i = 0; i < variant_defines.size(); i++) { _compile_variant(i, p_version); @@ -365,6 +490,9 @@ void ShaderRD::_compile_version(Version *p_version) { bool all_valid = true; for (int i = 0; i < variant_defines.size(); i++) { + if (!variants_enabled[i]) { + continue; //disabled + } if (p_version->variants[i].is_null()) { all_valid = false; break; @@ -374,6 +502,9 @@ void ShaderRD::_compile_version(Version *p_version) { if (!all_valid) { //clear versions if they exist for (int i = 0; i < variant_defines.size(); i++) { + if (!variants_enabled[i]) { + continue; //disabled + } if (!p_version->variants[i].is_null()) { RD::get_singleton()->free(p_version->variants[i]); } @@ -454,12 +585,26 @@ bool ShaderRD::version_free(RID p_version) { return true; } +void ShaderRD::set_variant_enabled(int p_variant, bool p_enabled) { + ERR_FAIL_COND(version_owner.get_rid_count() > 0); //versions exist + ERR_FAIL_INDEX(p_variant, variants_enabled.size()); + variants_enabled.write[p_variant] = p_enabled; +} + +bool ShaderRD::is_variant_enabled(int p_variant) const { + ERR_FAIL_INDEX_V(p_variant, variants_enabled.size(), false); + return variants_enabled[p_variant]; +} + void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String &p_general_defines) { ERR_FAIL_COND(variant_defines.size()); ERR_FAIL_COND(p_variant_defines.size() == 0); + general_defines = p_general_defines.utf8(); + for (int i = 0; i < p_variant_defines.size(); i++) { variant_defines.push_back(p_variant_defines[i].utf8()); + variants_enabled.push_back(true); } } diff --git a/servers/rendering/rasterizer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 0c379db6f2..a3474c6f93 100644 --- a/servers/rendering/rasterizer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -36,6 +36,7 @@ #include "core/templates/map.h" #include "core/templates/rid_owner.h" #include "core/variant/variant.h" +#include "servers/rendering_server.h" #include <stdio.h> /** @@ -46,6 +47,7 @@ class ShaderRD { //versions CharString general_defines; Vector<CharString> variant_defines; + Vector<bool> variants_enabled; struct Version { CharString uniforms; @@ -109,6 +111,7 @@ public: _FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) { ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID()); + ERR_FAIL_COND_V(!variants_enabled[p_variant], RID()); Version *version = version_owner.getornull(p_version); ERR_FAIL_COND_V(!version, RID()); @@ -128,6 +131,11 @@ public: bool version_free(RID p_version); + void set_variant_enabled(int p_variant, bool p_enabled); + bool is_variant_enabled(int p_variant) const; + + RS::ShaderNativeSourceCode version_get_native_source_code(RID p_version); + void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = ""); virtual ~ShaderRD(); }; diff --git a/servers/rendering/rasterizer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub index 4cddf0f685..deaa9668df 100644 --- a/servers/rendering/rasterizer_rd/shaders/SCsub +++ b/servers/rendering/renderer_rd/shaders/SCsub @@ -11,7 +11,7 @@ if "RD_GLSL" in env["BUILDERS"]: env.RD_GLSL("cubemap_roughness.glsl") env.RD_GLSL("cubemap_downsampler.glsl") env.RD_GLSL("cubemap_filter.glsl") - env.RD_GLSL("scene_high_end.glsl") + env.RD_GLSL("scene_forward.glsl") env.RD_GLSL("sky.glsl") env.RD_GLSL("tonemap.glsl") env.RD_GLSL("cube_to_dp.glsl") @@ -21,8 +21,10 @@ if "RD_GLSL" in env["BUILDERS"]: env.RD_GLSL("luminance_reduce.glsl") env.RD_GLSL("bokeh_dof.glsl") env.RD_GLSL("ssao.glsl") - env.RD_GLSL("ssao_minify.glsl") + env.RD_GLSL("ssao_downsample.glsl") + env.RD_GLSL("ssao_importance_map.glsl") env.RD_GLSL("ssao_blur.glsl") + env.RD_GLSL("ssao_interleave.glsl") env.RD_GLSL("roughness_limiter.glsl") env.RD_GLSL("screen_space_reflection.glsl") env.RD_GLSL("screen_space_reflection_filter.glsl") @@ -41,3 +43,4 @@ if "RD_GLSL" in env["BUILDERS"]: env.RD_GLSL("particles.glsl") env.RD_GLSL("particles_copy.glsl") env.RD_GLSL("sort.glsl") + env.RD_GLSL("skeleton.glsl") diff --git a/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl index 63f086a83d..63f086a83d 100644 --- a/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl +++ b/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index 51d7193a03..3b39edc70e 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -9,7 +9,8 @@ layout(location = 0) in vec2 vertex_attrib; layout(location = 3) in vec4 color_attrib; layout(location = 4) in vec2 uv_attrib; -layout(location = 6) in uvec4 bones_attrib; +layout(location = 10) in uvec4 bone_attrib; +layout(location = 11) in vec4 weight_attrib; #endif @@ -61,6 +62,7 @@ void main() { color = vec4(unpackHalf2x16(draw_data.colors[4]), unpackHalf2x16(draw_data.colors[5])); } uvec4 bones = uvec4(0, 0, 0, 0); + vec4 bone_weights = vec4(0.0); #elif defined(USE_ATTRIBUTES) @@ -68,7 +70,8 @@ void main() { vec4 color = color_attrib; vec2 uv = uv_attrib; - uvec4 bones = bones_attrib; + uvec4 bones = bone_attrib; + vec4 bone_weights = weight_attrib; #else vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); @@ -393,7 +396,7 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv vec4 shadow_color = unpackUnorm4x8(light_array.data[light_base].shadow_color); #ifdef LIGHT_SHADER_CODE_USED - shadow_color *= shadow_modulate; + shadow_color.rgb *= shadow_modulate; #endif shadow_color.a *= light_color.a; //respect light alpha @@ -494,9 +497,9 @@ void main() { vec2 shadow_vertex = vertex; { - float normal_depth = 1.0; + float normal_map_depth = 1.0; -#if defined(NORMALMAP_USED) +#if defined(NORMAL_MAP_USED) vec3 normal_map = vec3(0.0, 0.0, 1.0); normal_used = true; #endif @@ -507,8 +510,8 @@ FRAGMENT_SHADER_CODE /* clang-format on */ -#if defined(NORMALMAP_USED) - normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth); +#if defined(NORMAL_MAP_USED) + normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_map_depth); #endif } @@ -543,7 +546,7 @@ FRAGMENT_SHADER_CODE #ifdef LIGHT_SHADER_CODE_USED vec4 shadow_modulate = vec4(1.0); - light_color = light_compute(light_vertex, direction, normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv, true); + light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, true); #else if (normal_used) { @@ -560,7 +563,7 @@ FRAGMENT_SHADER_CODE light_color = light_shadow_compute(light_base, light_color, shadow_uv #ifdef LIGHT_SHADER_CODE_USED , - shadow_modulate + shadow_modulate.rgb #endif ); } @@ -602,7 +605,7 @@ FRAGMENT_SHADER_CODE vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height); light_color.rgb *= light_base_color.rgb; - light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv, false); + light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, false); #else light_color.rgb *= light_base_color.rgb * light_base_color.a; @@ -656,7 +659,7 @@ FRAGMENT_SHADER_CODE light_color = light_shadow_compute(light_base, light_color, shadow_uv #ifdef LIGHT_SHADER_CODE_USED , - shadow_modulate + shadow_modulate.rgb #endif ); } diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl index 5c25235c58..5c25235c58 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl b/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl index 302ad03b41..302ad03b41 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas_sdf.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index cf7678ea31..cf7678ea31 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/cluster_data_inc.glsl b/servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl index e723468dd8..e723468dd8 100644 --- a/servers/rendering/rasterizer_rd/shaders/cluster_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/renderer_rd/shaders/copy.glsl index cdd35dfb3f..cdd35dfb3f 100644 --- a/servers/rendering/rasterizer_rd/shaders/copy.glsl +++ b/servers/rendering/renderer_rd/shaders/copy.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl index 9751e13b4e..9751e13b4e 100644 --- a/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl index 54d67db6c6..54d67db6c6 100644 --- a/servers/rendering/rasterizer_rd/shaders/cube_to_dp.glsl +++ b/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl b/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl index 7f269b7af3..7f269b7af3 100644 --- a/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl b/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl index 987545fb76..987545fb76 100644 --- a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl index 5cbb00baa4..5cbb00baa4 100644 --- a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl index 8011dadc72..8011dadc72 100644 --- a/servers/rendering/rasterizer_rd/shaders/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/gi.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/giprobe.glsl index ea4237a45e..4f4753d147 100644 --- a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe.glsl @@ -208,6 +208,15 @@ float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) { return occlusion; //max(0.0,distance); } +float get_omni_attenuation(float distance, float inv_range, float decay) { + float nd = distance * inv_range; + nd *= nd; + nd *= nd; // nd^4 + nd = max(1.0 - nd, 0.0); + nd *= nd; // nd^2 + return nd * pow(max(distance, 0.0001), -decay); +} + bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) { if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) { light_pos = pos - lights.data[light].direction * length(vec3(params.limits)); @@ -220,7 +229,7 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 return false; } - attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation); + attenuation = get_omni_attenuation(distance, 1.0 / lights.data[light].radius, lights.data[light].attenuation); if (lights.data[light].type == LIGHT_TYPE_SPOT) { vec3 rel = normalize(pos - light_pos); diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl b/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl index 515cc35507..515cc35507 100644 --- a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl b/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl index 5b3dec0ee7..5b3dec0ee7 100644 --- a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl index 9c794f1bcc..9c794f1bcc 100644 --- a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl index 8a11c35b78..8a11c35b78 100644 --- a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl +++ b/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index 926c7ef9fc..cb6d8dc7f6 100644 --- a/servers/rendering/rasterizer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -173,7 +173,7 @@ uint hash(uint x) { return x; } -bool emit_particle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom, uint p_flags) { +bool emit_subparticle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom, uint p_flags) { if (!params.can_emit) { return false; } diff --git a/servers/rendering/rasterizer_rd/shaders/particles_copy.glsl b/servers/rendering/renderer_rd/shaders/particles_copy.glsl index 6c782b6045..6c782b6045 100644 --- a/servers/rendering/rasterizer_rd/shaders/particles_copy.glsl +++ b/servers/rendering/renderer_rd/shaders/particles_copy.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/resolve.glsl b/servers/rendering/renderer_rd/shaders/resolve.glsl index 9429a66dc9..9429a66dc9 100644 --- a/servers/rendering/rasterizer_rd/shaders/resolve.glsl +++ b/servers/rendering/renderer_rd/shaders/resolve.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl b/servers/rendering/renderer_rd/shaders/roughness_limiter.glsl index 464895928a..464895928a 100644 --- a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl +++ b/servers/rendering/renderer_rd/shaders/roughness_limiter.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/renderer_rd/shaders/scene_forward.glsl index 285698f060..0518976322 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward.glsl @@ -4,13 +4,19 @@ VERSION_DEFINES -#include "scene_high_end_inc.glsl" +#include "scene_forward_inc.glsl" /* INPUT ATTRIBS */ layout(location = 0) in vec3 vertex_attrib; + +//only for pure render depth when normal is not used + +#ifdef NORMAL_USED layout(location = 1) in vec3 normal_attrib; -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#endif + +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) layout(location = 2) in vec4 tangent_attrib; #endif @@ -18,30 +24,59 @@ layout(location = 2) in vec4 tangent_attrib; layout(location = 3) in vec4 color_attrib; #endif +#ifdef UV_USED layout(location = 4) in vec2 uv_attrib; +#endif #if defined(UV2_USED) || defined(USE_LIGHTMAP) || defined(MODE_RENDER_MATERIAL) layout(location = 5) in vec2 uv2_attrib; #endif -layout(location = 6) in uvec4 bone_attrib; // always bound, even if unused +#if defined(CUSTOM0_USED) +layout(location = 6) in vec4 custom0_attrib; +#endif + +#if defined(CUSTOM1_USED) +layout(location = 7) in vec4 custom1_attrib; +#endif + +#if defined(CUSTOM2_USED) +layout(location = 8) in vec4 custom2_attrib; +#endif + +#if defined(CUSTOM3_USED) +layout(location = 9) in vec4 custom3_attrib; +#endif + +#if defined(BONES_USED) +layout(location = 10) in uvec4 bone_attrib; +#endif + +#if defined(WEIGHTS_USED) +layout(location = 11) in vec4 weight_attrib; +#endif /* Varyings */ layout(location = 0) out vec3 vertex_interp; + +#ifdef NORMAL_USED layout(location = 1) out vec3 normal_interp; +#endif #if defined(COLOR_USED) layout(location = 2) out vec4 color_interp; #endif +#ifdef UV_USED layout(location = 3) out vec2 uv_interp; +#endif #if defined(UV2_USED) || defined(USE_LIGHTMAP) layout(location = 4) out vec2 uv2_interp; #endif -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) layout(location = 5) out vec3 tangent_interp; layout(location = 6) out vec3 binormal_interp; #endif @@ -62,8 +97,6 @@ VERTEX_SHADER_GLOBALS invariant gl_Position; -layout(location = 7) flat out uint instance_index; - #ifdef MODE_DUAL_PARABOLOID layout(location = 8) out float dp_clip; @@ -71,22 +104,27 @@ layout(location = 8) out float dp_clip; #endif void main() { - instance_index = draw_call.instance_index; vec4 instance_custom = vec4(0.0); #if defined(COLOR_USED) color_interp = color_attrib; #endif - mat4 world_matrix = instances.data[instance_index].transform; - mat3 world_normal_matrix = mat3(instances.data[instance_index].normal_transform); + mat4 world_matrix = draw_call.transform; + + mat3 world_normal_matrix; + if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { + world_normal_matrix = inverse(mat3(world_matrix)); + } else { + world_normal_matrix = mat3(world_matrix); + } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) { + if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH)) { //multimesh, instances are for it - uint offset = (instances.data[instance_index].flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK; + uint offset = (draw_call.flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK; offset *= gl_InstanceIndex; mat4 matrix; - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { + if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); offset += 2; } else { @@ -94,14 +132,14 @@ void main() { offset += 3; } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { + if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { #ifdef COLOR_USED color_interp *= transforms.data[offset]; #endif offset += 1; } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { + if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { instance_custom = transforms.data[offset]; } @@ -109,22 +147,21 @@ void main() { matrix = transpose(matrix); world_matrix = world_matrix * matrix; world_normal_matrix = world_normal_matrix * mat3(matrix); - - } else { - //not a multimesh, instances are for multiple draw calls - instance_index += gl_InstanceIndex; } vec3 vertex = vertex_attrib; - vec3 normal = normal_attrib; +#ifdef NORMAL_USED + vec3 normal = normal_attrib * 2.0 - 1.0; +#endif -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec3 tangent = tangent_attrib.xyz; - float binormalf = tangent_attrib.a; +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) + vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0; + float binormalf = tangent_attrib.a * 2.0 - 1.0; vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) { +#if 0 + if (bool(draw_call.flags & INSTANCE_FLAGS_SKELETON)) { //multimesh, instances are for it uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3; @@ -141,14 +178,17 @@ void main() { vertex = (vec4(vertex, 1.0) * m).xyz; normal = (vec4(normal, 0.0) * m).xyz; -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) tangent = (vec4(tangent, 0.0) * m).xyz; binormal = (vec4(binormal, 0.0) * m).xyz; #endif } +#endif +#ifdef UV_USED uv_interp = uv_attrib; +#endif #if defined(UV2_USED) || defined(USE_LIGHTMAP) uv2_interp = uv2_attrib; @@ -167,7 +207,7 @@ void main() { normal = world_normal_matrix * normal; -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) tangent = world_normal_matrix * tangent; binormal = world_normal_matrix * binormal; @@ -192,10 +232,13 @@ VERTEX_SHADER_CODE #if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) vertex = (modelview * vec4(vertex, 1.0)).xyz; +#ifdef NORMAL_USED normal = modelview_normal * normal; #endif -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#endif + +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) binormal = modelview_normal * binormal; tangent = modelview_normal * tangent; @@ -207,7 +250,7 @@ VERTEX_SHADER_CODE vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz; normal = mat3(scene_data.inverse_normal_matrix) * normal; -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) binormal = mat3(scene_data.camera_inverse_binormal_matrix) * binormal; tangent = mat3(scene_data.camera_inverse_tangent_matrix) * tangent; @@ -215,9 +258,11 @@ VERTEX_SHADER_CODE #endif vertex_interp = vertex; +#ifdef NORMAL_USED normal_interp = normal; +#endif -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) tangent_interp = tangent; binormal_interp = binormal; #endif @@ -227,7 +272,6 @@ VERTEX_SHADER_CODE #ifdef MODE_DUAL_PARABOLOID vertex_interp.z *= scene_data.dual_paraboloid_side; - normal_interp.z *= scene_data.dual_paraboloid_side; dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias @@ -260,7 +304,7 @@ VERTEX_SHADER_CODE #endif #ifdef MODE_RENDER_MATERIAL if (scene_data.material_uv2_mode) { - gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0; + gl_Position.xy = (uv2_attrib.xy + draw_call.lightmap_uv_scale.xy) * 2.0 - 1.0; gl_Position.z = 0.00001; gl_Position.w = 1.0; } @@ -273,30 +317,33 @@ VERTEX_SHADER_CODE VERSION_DEFINES -#include "scene_high_end_inc.glsl" +#include "scene_forward_inc.glsl" /* Varyings */ layout(location = 0) in vec3 vertex_interp; + +#ifdef NORMAL_USED layout(location = 1) in vec3 normal_interp; +#endif #if defined(COLOR_USED) layout(location = 2) in vec4 color_interp; #endif +#ifdef UV_USED layout(location = 3) in vec2 uv_interp; +#endif #if defined(UV2_USED) || defined(USE_LIGHTMAP) layout(location = 4) in vec2 uv2_interp; #endif -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) layout(location = 5) in vec3 tangent_interp; layout(location = 6) in vec3 binormal_interp; #endif -layout(location = 7) flat in uint instance_index; - #ifdef MODE_DUAL_PARABOLOID layout(location = 8) in float dp_clip; @@ -305,8 +352,7 @@ layout(location = 8) in float dp_clip; //defines to keep compatibility with vertex -#define world_matrix instances.data[instance_index].transform -#define world_normal_matrix instances.data[instance_index].normal_transform +#define world_matrix draw_call.transform #define projection_matrix scene_data.projection_matrix #if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE) @@ -845,6 +891,15 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex #endif //USE_NO_SHADOWS +float get_omni_attenuation(float distance, float inv_range, float decay) { + float nd = distance * inv_range; + nd *= nd; + nd *= nd; // nd^4 + nd = max(1.0 - nd, 0.0); + nd *= nd; // nd^2 + return nd * pow(max(distance, 0.0001), -decay); +} + void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity, #ifdef LIGHT_BACKLIGHT_USED vec3 backlight, @@ -870,9 +925,8 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v inout vec3 diffuse_light, inout vec3 specular_light) { vec3 light_rel_vec = lights.data[idx].position - vertex; float light_length = length(light_rel_vec); - float normalized_distance = light_length * lights.data[idx].inv_radius; vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy); - float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x); + float omni_attenuation = get_omni_attenuation(light_length, lights.data[idx].inv_radius, attenuation_energy.x); float light_attenuation = omni_attenuation; vec3 shadow_attenuation = vec3(1.0); vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular); @@ -1159,9 +1213,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v inout vec3 specular_light) { vec3 light_rel_vec = lights.data[idx].position - vertex; float light_length = length(light_rel_vec); - float normalized_distance = light_length * lights.data[idx].inv_radius; vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy); - float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x); + float spot_attenuation = get_omni_attenuation(light_length, lights.data[idx].inv_radius, attenuation_energy.x); vec3 spot_dir = lights.data[idx].direction; vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle); float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y); @@ -1525,8 +1578,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 out_spec += vec4(irr_light.rgb * blend, blend); } -#endif //USE_FORWARD_GI - vec2 octahedron_wrap(vec2 v) { vec2 signVal; signVal.x = v.x >= 0.0 ? 1.0 : -1.0; @@ -1660,10 +1711,14 @@ void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal } } +#endif //USE_FORWARD_GI + #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) #ifndef MODE_RENDER_DEPTH +#ifndef LOW_END_MODE + vec4 volumetric_fog_process(vec2 screen_uv, float z) { vec3 fog_pos = vec3(screen_uv, z * scene_data.volumetric_fog_inv_length); if (fog_pos.z < 0.0) { @@ -1674,6 +1729,7 @@ vec4 volumetric_fog_process(vec2 screen_uv, float z) { return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos); } +#endif vec4 fog_process(vec3 vertex) { vec3 fog_color = scene_data.fog_light_color; @@ -1766,13 +1822,15 @@ void main() { float alpha = 1.0; -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) vec3 binormal = normalize(binormal_interp); vec3 tangent = normalize(tangent_interp); #else vec3 binormal = vec3(0.0); vec3 tangent = vec3(0.0); #endif + +#ifdef NORMAL_USED vec3 normal = normalize(normal_interp); #if defined(DO_SIDE_CHECK) @@ -1781,7 +1839,11 @@ void main() { } #endif +#endif //NORMAL_USED + +#ifdef UV_USED vec2 uv = uv_interp; +#endif #if defined(UV2_USED) || defined(USE_LIGHTMAP) vec2 uv2 = uv2_interp; @@ -1791,12 +1853,12 @@ void main() { vec4 color = color_interp; #endif -#if defined(NORMALMAP_USED) +#if defined(NORMAL_MAP_USED) - vec3 normalmap = vec3(0.5); + vec3 normal_map = vec3(0.5); #endif - float normaldepth = 1.0; + float normal_map_depth = 1.0; vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center @@ -1867,12 +1929,12 @@ FRAGMENT_SHADER_CODE #endif // !USE_SHADOW_TO_OPACITY -#ifdef NORMALMAP_USED +#ifdef NORMAL_MAP_USED - normalmap.xy = normalmap.xy * 2.0 - 1.0; - normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. + normal_map.xy = normal_map.xy * 2.0 - 1.0; + normal_map.z = sqrt(max(0.0, 1.0 - dot(normal_map.xy, normal_map.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. - normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)); + normal = normalize(mix(normal, tangent * normal_map.x + binormal * normal_map.y + normal * normal_map.z, normal_map_depth)); #endif @@ -1912,7 +1974,7 @@ FRAGMENT_SHADER_CODE for (uint i = 0; i < decal_count; i++) { uint decal_index = cluster_data.indices[decal_pointer + i]; - if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) { + if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) { continue; //not masked } @@ -1968,6 +2030,7 @@ FRAGMENT_SHADER_CODE #endif //not render depth /////////////////////// LIGHTING ////////////////////////////// +#ifdef NORMAL_USED if (scene_data.roughness_limiter_enabled) { //http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf float roughness2 = roughness * roughness; @@ -1977,6 +2040,7 @@ FRAGMENT_SHADER_CODE float filteredRoughness2 = min(1.0, roughness2 + kernelRoughness2); roughness = sqrt(filteredRoughness2); } +#endif //apply energy conservation vec3 specular_light = vec3(0.0, 0.0, 0.0); @@ -2041,8 +2105,8 @@ FRAGMENT_SHADER_CODE #ifdef USE_LIGHTMAP //lightmap - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture - uint index = instances.data[instance_index].gi_offset; + if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture + uint index = draw_call.gi_offset; vec3 wnormal = mat3(scene_data.camera_matrix) * normal; const float c1 = 0.429043; @@ -2061,12 +2125,12 @@ FRAGMENT_SHADER_CODE 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y + 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z); - } else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap - bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); - uint ofs = instances.data[instance_index].gi_offset & 0xFFF; + } else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap + bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); + uint ofs = draw_call.gi_offset & 0xFFFF; vec3 uvw; - uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy; - uvw.z = float((instances.data[instance_index].gi_offset >> 12) & 0xFF); + uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy; + uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF); if (uses_sh) { uvw.z *= 4.0; //SH textures use 4 times more data @@ -2075,7 +2139,7 @@ FRAGMENT_SHADER_CODE vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb; vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb; - uint idx = instances.data[instance_index].gi_offset >> 20; + uint idx = draw_call.gi_offset >> 20; vec3 n = normalize(lightmaps.data[idx].normal_xform * normal); ambient_light += lm_light_l0 * 0.282095f; @@ -2095,7 +2159,7 @@ FRAGMENT_SHADER_CODE } #elif defined(USE_FORWARD_GI) - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture + if (bool(draw_call.flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture //make vertex orientation the world one, but still align to camera vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex; @@ -2167,9 +2231,9 @@ FRAGMENT_SHADER_CODE } } - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes + if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes - uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; + uint index1 = draw_call.gi_offset & 0xFFFF; vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); //find arbitrary tangent and bitangent, then build a matrix vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); @@ -2181,7 +2245,7 @@ FRAGMENT_SHADER_CODE vec4 spec_accum = vec4(0.0); gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); - uint index2 = instances.data[instance_index].gi_offset >> 16; + uint index2 = draw_call.gi_offset >> 16; if (index2 != 0xFFFF) { gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); @@ -2198,30 +2262,13 @@ FRAGMENT_SHADER_CODE specular_light = spec_accum.rgb; ambient_light = amb_accum.rgb; } -#else - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers +#elif !defined(LOW_END_MODE) + + if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers ivec2 coord; if (scene_data.gi_upscale_for_msaa) { - /* - //find the closest depth to upscale from, based on neighbours - ivec2 base_coord = ivec2(gl_FragCoord.xy); - float z_dist = gl_FragCoord.z; - ivec2 closest_coord = base_coord; - float closest_z_dist = abs(texelFetch(sampler2D(depth_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord,0).r-z_dist); - - for(int i=0;i<4;i++) { - const ivec2 neighbours[4]=ivec2[](ivec2(-1,0),ivec2(1,0),ivec2(0,-1),ivec2(0,1)); - ivec2 neighbour_coord = base_coord + neighbours[i]; - float neighbour_z_dist = abs(texelFetch(sampler2D(depth_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord,0).r-z_dist); - if (neighbour_z_dist < closest_z_dist) { - closest_z_dist = neighbour_z_dist; - closest_coord = neighbour_coord; - } - } - -*/ ivec2 base_coord = ivec2(gl_FragCoord.xy); ivec2 closest_coord = base_coord; float closest_ang = dot(normal, texelFetch(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0).xyz * 2.0 - 1.0); @@ -2299,7 +2346,7 @@ FRAGMENT_SHADER_CODE { //directional light for (uint i = 0; i < scene_data.directional_light_count; i++) { - if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) { + if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) { continue; //not masked } @@ -2569,7 +2616,7 @@ FRAGMENT_SHADER_CODE for (uint i = 0; i < omni_light_count; i++) { uint light_index = cluster_data.indices[omni_light_pointer + i]; - if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { + if (!bool(lights.data[light_index].mask & draw_call.layer_mask)) { continue; //not masked } @@ -2607,7 +2654,7 @@ FRAGMENT_SHADER_CODE for (uint i = 0; i < spot_light_count; i++) { uint light_index = cluster_data.indices[spot_light_pointer + i]; - if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { + if (!bool(lights.data[light_index].mask & draw_call.layer_mask)) { continue; //not masked } @@ -2778,9 +2825,9 @@ FRAGMENT_SHADER_CODE normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness); #ifdef MODE_RENDER_GIPROBE - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes - uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; - uint index2 = instances.data[instance_index].gi_offset >> 16; + if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes + uint index1 = draw_call.gi_offset & 0xFFFF; + uint index2 = draw_call.gi_offset >> 16; giprobe_buffer.x = index1 & 0xFF; giprobe_buffer.y = index2 & 0xFF; } else { @@ -2800,11 +2847,13 @@ FRAGMENT_SHADER_CODE //ambient occlusion #if defined(AO_USED) +#ifndef LOW_END_MODE if (scene_data.ssao_enabled && scene_data.ssao_ao_affect > 0.0) { float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; ao = mix(ao, min(ao, ssao), scene_data.ssao_ao_affect); ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect); } +#endif //LOW_END_MODE ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao); ao_light_affect = mix(1.0, ao, ao_light_affect); @@ -2812,6 +2861,7 @@ FRAGMENT_SHADER_CODE diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect); #else +#ifndef LOW_END_MODE if (scene_data.ssao_enabled) { float ao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao); @@ -2819,6 +2869,7 @@ FRAGMENT_SHADER_CODE specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect); diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect); } +#endif //LOW_END_MODE #endif // AO_USED @@ -2848,11 +2899,13 @@ FRAGMENT_SHADER_CODE specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a); } +#ifndef LOW_END_MODE if (scene_data.volumetric_fog_enabled) { vec4 fog = volumetric_fog_process(screen_uv, -vertex.z); diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a); specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a); } +#endif // LOW_END_MODE #if defined(CUSTOM_FOG_USED) diffuse_buffer.rgb = mix(diffuse_buffer.rgb, custom_fog.rgb, custom_fog.a); @@ -2873,11 +2926,12 @@ FRAGMENT_SHADER_CODE vec4 fog = fog_process(vertex); frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); } - +#ifndef LOW_END_MODE if (scene_data.volumetric_fog_enabled) { vec4 fog = volumetric_fog_process(screen_uv, -vertex.z); frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); } +#endif #if defined(CUSTOM_FOG_USED) frag_color.rgb = mix(frag_color.rgb, custom_fog.rgb, custom_fog.a); diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl index e29a490ca1..87ce74ba88 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl @@ -5,10 +5,19 @@ #include "cluster_data_inc.glsl" +#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_GIPROBE) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) +#ifndef NORMAL_USED +#define NORMAL_USED +#endif +#endif + layout(push_constant, binding = 0, std430) uniform DrawCall { - uint instance_index; - uint pad; //16 bits minimum size - vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise + mat4 transform; + uint flags; + uint instance_uniforms_ofs; //base offset in global buffer for instance variables + uint gi_offset; //GI information when using lightmapping (VCT or lightmap index) + uint layer_mask; + vec4 lightmap_uv_scale; } draw_call; @@ -128,21 +137,7 @@ scene_data; #define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7 #define INSTANCE_FLAGS_SKELETON (1 << 19) - -struct InstanceData { - mat4 transform; - mat4 normal_transform; - uint flags; - uint instance_uniforms_ofs; //base offset in global buffer for instance variables - uint gi_offset; //GI information when using lightmapping (VCT or lightmap index) - uint layer_mask; - vec4 lightmap_uv_scale; -}; - -layout(set = 0, binding = 4, std430) restrict readonly buffer Instances { - InstanceData data[]; -} -instances; +#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 20) layout(set = 0, binding = 5, std430) restrict readonly buffer Lights { LightData data[]; @@ -171,39 +166,39 @@ layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps { } lightmaps; -layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; - struct LightmapCapture { vec4 sh[9]; }; -layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures { +layout(set = 0, binding = 11, std140) restrict readonly buffer LightmapCaptures { LightmapCapture data[]; } lightmap_captures; -layout(set = 0, binding = 13) uniform texture2D decal_atlas; -layout(set = 0, binding = 14) uniform texture2D decal_atlas_srgb; +layout(set = 0, binding = 12) uniform texture2D decal_atlas; +layout(set = 0, binding = 13) uniform texture2D decal_atlas_srgb; -layout(set = 0, binding = 15, std430) restrict readonly buffer Decals { +layout(set = 0, binding = 14, std430) restrict readonly buffer Decals { DecalData data[]; } decals; -layout(set = 0, binding = 16) uniform utexture3D cluster_texture; +layout(set = 0, binding = 15) uniform utexture3D cluster_texture; -layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData { +layout(set = 0, binding = 16, std430) restrict readonly buffer ClusterData { uint indices[]; } cluster_data; -layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas; +layout(set = 0, binding = 17) uniform texture2D directional_shadow_atlas; -layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 18, std430) restrict readonly buffer GlobalVariableData { vec4 data[]; } global_variables; +#ifndef LOW_END_MODE + struct SDFGIProbeCascadeData { vec3 position; float to_probe; @@ -211,7 +206,7 @@ struct SDFGIProbeCascadeData { float to_cell; // 1/bounds * grid_size }; -layout(set = 0, binding = 20, std140) uniform SDFGI { +layout(set = 0, binding = 19, std140) uniform SDFGI { vec3 grid_size; uint max_cascades; @@ -239,6 +234,8 @@ layout(set = 0, binding = 20, std140) uniform SDFGI { } sdfgi; +#endif //LOW_END_MODE + // decal atlas /* Set 1, Radiance */ @@ -255,20 +252,24 @@ layout(set = 1, binding = 0) uniform textureCube radiance_cubemap; /* Set 2, Reflection and Shadow Atlases (view dependent) */ -layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas; +layout(set = 1, binding = 1) uniform textureCubeArray reflection_atlas; + +layout(set = 1, binding = 2) uniform texture2D shadow_atlas; -layout(set = 2, binding = 1) uniform texture2D shadow_atlas; +layout(set = 1, binding = 3) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; -layout(set = 2, binding = 2) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; +#ifndef LOW_END_MODE +layout(set = 1, binding = 4) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; +#endif /* Set 3, Render Buffers */ #ifdef MODE_RENDER_SDF -layout(r16ui, set = 3, binding = 0) uniform restrict writeonly uimage3D albedo_volume_grid; -layout(r32ui, set = 3, binding = 1) uniform restrict writeonly uimage3D emission_grid; -layout(r32ui, set = 3, binding = 2) uniform restrict writeonly uimage3D emission_aniso_grid; -layout(r32ui, set = 3, binding = 3) uniform restrict uimage3D geom_facing_grid; +layout(r16ui, set = 1, binding = 5) uniform restrict writeonly uimage3D albedo_volume_grid; +layout(r32ui, set = 1, binding = 6) uniform restrict writeonly uimage3D emission_grid; +layout(r32ui, set = 1, binding = 7) uniform restrict writeonly uimage3D emission_aniso_grid; +layout(r32ui, set = 1, binding = 8) uniform restrict uimage3D geom_facing_grid; //still need to be present for shaders that use it, so remap them to something #define depth_buffer shadow_atlas @@ -277,14 +278,17 @@ layout(r32ui, set = 3, binding = 3) uniform restrict uimage3D geom_facing_grid; #else -layout(set = 3, binding = 0) uniform texture2D depth_buffer; -layout(set = 3, binding = 1) uniform texture2D color_buffer; -layout(set = 3, binding = 2) uniform texture2D normal_roughness_buffer; -layout(set = 3, binding = 4) uniform texture2D ao_buffer; -layout(set = 3, binding = 5) uniform texture2D ambient_buffer; -layout(set = 3, binding = 6) uniform texture2D reflection_buffer; -layout(set = 3, binding = 7) uniform texture2DArray sdfgi_lightprobe_texture; -layout(set = 3, binding = 8) uniform texture3D sdfgi_occlusion_cascades; +layout(set = 1, binding = 5) uniform texture2D depth_buffer; +layout(set = 1, binding = 6) uniform texture2D color_buffer; + +#ifndef LOW_END_MODE + +layout(set = 1, binding = 7) uniform texture2D normal_roughness_buffer; +layout(set = 1, binding = 8) uniform texture2D ao_buffer; +layout(set = 1, binding = 9) uniform texture2D ambient_buffer; +layout(set = 1, binding = 10) uniform texture2D reflection_buffer; +layout(set = 1, binding = 11) uniform texture2DArray sdfgi_lightprobe_texture; +layout(set = 1, binding = 12) uniform texture3D sdfgi_occlusion_cascades; struct GIProbeData { mat4 xform; @@ -302,18 +306,20 @@ struct GIProbeData { uint mipmaps; }; -layout(set = 3, binding = 9, std140) uniform GIProbes { +layout(set = 1, binding = 13, std140) uniform GIProbes { GIProbeData data[MAX_GI_PROBES]; } gi_probes; -layout(set = 3, binding = 10) uniform texture3D volumetric_fog_texture; +layout(set = 1, binding = 14) uniform texture3D volumetric_fog_texture; + +#endif // LOW_END_MODE #endif /* Set 4 Skeleton & Instancing (Multimesh) */ -layout(set = 4, binding = 0, std430) restrict readonly buffer Transforms { +layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms { vec4 data[]; } transforms; diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl index 06dc4b13de..06dc4b13de 100644 --- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl index a5afe74cb2..a5afe74cb2 100644 --- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl +++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl index 218605a962..218605a962 100644 --- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection_scale.glsl +++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl index 813ea29fa1..813ea29fa1 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl index 08da283dad..08da283dad 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl index 61e4bf5e18..30dbf5871f 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl @@ -112,6 +112,15 @@ vec2 octahedron_encode(vec3 n) { return n.xy; } +float get_omni_attenuation(float distance, float inv_range, float decay) { + float nd = distance * inv_range; + nd *= nd; + nd *= nd; // nd^4 + nd = max(1.0 - nd, 0.0); + nd *= nd; // nd^2 + return nd * pow(max(distance, 0.0001), -decay); +} + void main() { uint voxel_index = uint(gl_GlobalInvocationID.x); @@ -184,14 +193,15 @@ void main() { direction = normalize(rel_vec); light_distance = length(rel_vec); rel_vec.y /= params.y_mult; - attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation); + attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation); + } break; case LIGHT_TYPE_SPOT: { vec3 rel_vec = lights.data[i].position - position; direction = normalize(rel_vec); light_distance = length(rel_vec); rel_vec.y /= params.y_mult; - attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation); + attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation); float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction)); if (angle > lights.data[i].spot_angle) { diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_fields.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_fields.glsl index eec0a90c0d..69d8824d8a 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_fields.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_fields.glsl @@ -14,7 +14,7 @@ layout(local_size_x = OCT_RES, local_size_y = OCT_RES, local_size_z = 1) in; layout(rgba16f, set = 0, binding = 1) uniform restrict image2DArray irradiance_texture; layout(rg16f, set = 0, binding = 2) uniform restrict image2DArray depth_texture; -ayout(rgba32ui, set = 0, binding = 3) uniform restrict uimage2DArray irradiance_history_texture; +layout(rgba32ui, set = 0, binding = 3) uniform restrict uimage2DArray irradiance_history_texture; layout(rg32ui, set = 0, binding = 4) uniform restrict uimage2DArray depth_history_texture; struct CascadeData { diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl index d516ab22c3..d516ab22c3 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl index 916c60ac89..916c60ac89 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/shadow_reduce.glsl b/servers/rendering/renderer_rd/shaders/shadow_reduce.glsl index 29443ae7db..29443ae7db 100644 --- a/servers/rendering/rasterizer_rd/shaders/shadow_reduce.glsl +++ b/servers/rendering/renderer_rd/shaders/shadow_reduce.glsl diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl new file mode 100644 index 0000000000..b19f5a9ad3 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -0,0 +1,199 @@ +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +layout(set = 0, binding = 1, std430) buffer restrict writeonly DstVertexData { + uint data[]; +} +dst_vertices; + +layout(set = 0, binding = 2, std430) buffer restrict readonly BlendShapeWeights { + float data[]; +} +blend_shape_weights; + +layout(set = 1, binding = 0, std430) buffer restrict readonly SrcVertexData { + uint data[]; +} +src_vertices; + +layout(set = 1, binding = 1, std430) buffer restrict readonly BoneWeightData { + uint data[]; +} +src_bone_weights; + +layout(set = 1, binding = 2, std430) buffer restrict readonly BlendShapeData { + uint data[]; +} +src_blend_shapes; + +layout(set = 2, binding = 0, std430) buffer restrict readonly SkeletonData { + vec4 data[]; +} +bone_transforms; + +layout(push_constant, binding = 0, std430) uniform Params { + bool has_normal; + bool has_tangent; + bool has_skeleton; + bool has_blend_shape; + + uint vertex_count; + uint vertex_stride; + uint skin_stride; + uint skin_weight_offset; + + uint blend_shape_count; + bool normalized_blend_shapes; + uint pad0; + uint pad1; +} +params; + +vec4 decode_abgr_2_10_10_10(uint base) { + uvec4 abgr_2_10_10_10 = (uvec4(base) >> uvec4(0, 10, 20, 30)) & uvec4(0x3FF, 0x3FF, 0x3FF, 0x3); + return vec4(abgr_2_10_10_10) / vec4(1023.0, 1023.0, 1023.0, 3.0) * 2.0 - 1.0; +} + +uint encode_abgr_2_10_10_10(vec4 base) { + uvec4 abgr_2_10_10_10 = uvec4(clamp(ivec4((base * 0.5 + 0.5) * vec4(1023.0, 1023.0, 1023.0, 3.0)), ivec4(0), ivec4(0x3FF, 0x3FF, 0x3FF, 0x3))) << uvec4(0, 10, 20, 30); + return abgr_2_10_10_10.x | abgr_2_10_10_10.y | abgr_2_10_10_10.z | abgr_2_10_10_10.w; +} + +void main() { + uint index = gl_GlobalInvocationID.x; + if (index >= params.vertex_count) { + return; + } + + uint src_offset = index * params.vertex_stride; + +#ifdef MODE_2D + vec2 vertex = uintBitsToFloat(uvec2(src_vertices.data[src_offset + 0], src_vertices.data[src_offset + 1])); +#else + vec3 vertex; + vec3 normal; + vec4 tangent; + + vertex = uintBitsToFloat(uvec3(src_vertices.data[src_offset + 0], src_vertices.data[src_offset + 1], src_vertices.data[src_offset + 2])); + + src_offset += 3; + + if (params.has_normal) { + normal = decode_abgr_2_10_10_10(src_vertices.data[src_offset]).rgb; + src_offset++; + } + + if (params.has_tangent) { + tangent = decode_abgr_2_10_10_10(src_vertices.data[src_offset]); + } + + if (params.has_blend_shape) { + float blend_total = 0.0; + vec3 blend_vertex = vec3(0.0); + vec3 blend_normal = vec3(0.0); + vec3 blend_tangent = vec3(0.0); + + for (uint i = 0; i < params.blend_shape_count; i++) { + float w = blend_shape_weights.data[i]; + if (w > 0.0001) { + uint base_offset = (params.vertex_count * i + index) * params.vertex_stride; + + blend_vertex += uintBitsToFloat(uvec3(src_blend_shapes.data[base_offset + 0], src_blend_shapes.data[base_offset + 1], src_blend_shapes.data[base_offset + 2])) * w; + + base_offset += 3; + + if (params.has_normal) { + blend_normal += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w; + base_offset++; + } + + if (params.has_tangent) { + blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb; + } + + blend_total += w; + } + } + + if (params.normalized_blend_shapes) { + vertex = (1.0 - blend_total) * vertex; + normal = (1.0 - blend_total) * normal; + tangent.rgb = (1.0 - blend_total) * tangent.rgb; + } + + vertex += blend_vertex; + normal += normalize(normal + blend_normal); + tangent.rgb += normalize(tangent.rgb + blend_tangent); + } + + if (params.has_skeleton) { + uint skin_offset = params.skin_stride * index; + + uvec2 bones = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]); + uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 3; //pre-add xform offset + uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 3; + + skin_offset += params.skin_weight_offset; + + uvec2 weights = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]); + + vec2 weights_01 = unpackUnorm2x16(weights.x); + vec2 weights_23 = unpackUnorm2x16(weights.y); + + mat4 m = mat4(bone_transforms.data[bones_01.x], bone_transforms.data[bones_01.x + 1], bone_transforms.data[bones_01.x + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.x; + m += mat4(bone_transforms.data[bones_01.y], bone_transforms.data[bones_01.y + 1], bone_transforms.data[bones_01.y + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.y; + m += mat4(bone_transforms.data[bones_23.x], bone_transforms.data[bones_23.x + 1], bone_transforms.data[bones_23.x + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.x; + m += mat4(bone_transforms.data[bones_23.y], bone_transforms.data[bones_23.y + 1], bone_transforms.data[bones_23.y + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.y; + + if (params.skin_weight_offset == 4) { + //using 8 bones/weights + skin_offset = params.skin_stride * index + 2; + + bones = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]); + bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 3; //pre-add xform offset + bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 3; + + skin_offset += params.skin_weight_offset; + + weights = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]); + + weights_01 = unpackUnorm2x16(weights.x); + weights_23 = unpackUnorm2x16(weights.y); + + m += mat4(bone_transforms.data[bones_01.x], bone_transforms.data[bones_01.x + 1], bone_transforms.data[bones_01.x + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.x; + m += mat4(bone_transforms.data[bones_01.y], bone_transforms.data[bones_01.y + 1], bone_transforms.data[bones_01.y + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.y; + m += mat4(bone_transforms.data[bones_23.x], bone_transforms.data[bones_23.x + 1], bone_transforms.data[bones_23.x + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.x; + m += mat4(bone_transforms.data[bones_23.y], bone_transforms.data[bones_23.y + 1], bone_transforms.data[bones_23.y + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.y; + } + + //reverse order because its transposed + vertex = (vec4(vertex, 1.0) * m).xyz; + normal = normalize((vec4(normal, 0.0) * m).xyz); + tangent.xyz = normalize((vec4(tangent.xyz, 0.0) * m).xyz); + } + + uint dst_offset = index * params.vertex_stride; + + uvec3 uvertex = floatBitsToUint(vertex); + dst_vertices.data[dst_offset + 0] = uvertex.x; + dst_vertices.data[dst_offset + 1] = uvertex.y; + dst_vertices.data[dst_offset + 2] = uvertex.z; + + dst_offset += 3; + + if (params.has_normal) { + dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(vec4(normal, 0.0)); + dst_offset++; + } + + if (params.has_tangent) { + dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(tangent); + } + +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl index 6c985e1f5c..6c985e1f5c 100644 --- a/servers/rendering/rasterizer_rd/shaders/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/sky.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/sort.glsl b/servers/rendering/renderer_rd/shaders/sort.glsl index e5ebb9c64b..e5ebb9c64b 100644 --- a/servers/rendering/rasterizer_rd/shaders/sort.glsl +++ b/servers/rendering/renderer_rd/shaders/sort.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/specular_merge.glsl index 0b8f406213..0b8f406213 100644 --- a/servers/rendering/rasterizer_rd/shaders/specular_merge.glsl +++ b/servers/rendering/renderer_rd/shaders/specular_merge.glsl diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/ssao.glsl new file mode 100644 index 0000000000..231f8f91ec --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/ssao.glsl @@ -0,0 +1,486 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016, Intel Corporation +// 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. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// File changes (yyyy-mm-dd) +// 2016-09-07: filip.strugar@intel.com: first commit +// 2020-12-05: clayjohn: convert to Vulkan and Godot +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#[compute] + +#version 450 + +VERSION_DEFINES + +#define SSAO_ADAPTIVE_TAP_BASE_COUNT 5 + +#define INTELSSAO_MAIN_DISK_SAMPLE_COUNT (32) +const vec4 sample_pattern[INTELSSAO_MAIN_DISK_SAMPLE_COUNT] = { + vec4(0.78488064, 0.56661671, 1.500000, -0.126083), vec4(0.26022232, -0.29575172, 1.500000, -1.064030), vec4(0.10459357, 0.08372527, 1.110000, -2.730563), vec4(-0.68286800, 0.04963045, 1.090000, -0.498827), + vec4(-0.13570161, -0.64190155, 1.250000, -0.532765), vec4(-0.26193795, -0.08205118, 0.670000, -1.783245), vec4(-0.61177456, 0.66664219, 0.710000, -0.044234), vec4(0.43675563, 0.25119025, 0.610000, -1.167283), + vec4(0.07884444, 0.86618668, 0.640000, -0.459002), vec4(-0.12790935, -0.29869005, 0.600000, -1.729424), vec4(-0.04031125, 0.02413622, 0.600000, -4.792042), vec4(0.16201244, -0.52851415, 0.790000, -1.067055), + vec4(-0.70991218, 0.47301072, 0.640000, -0.335236), vec4(0.03277707, -0.22349690, 0.600000, -1.982384), vec4(0.68921727, 0.36800742, 0.630000, -0.266718), vec4(0.29251814, 0.37775412, 0.610000, -1.422520), + vec4(-0.12224089, 0.96582592, 0.600000, -0.426142), vec4(0.11071457, -0.16131058, 0.600000, -2.165947), vec4(0.46562141, -0.59747696, 0.600000, -0.189760), vec4(-0.51548797, 0.11804193, 0.600000, -1.246800), + vec4(0.89141309, -0.42090443, 0.600000, 0.028192), vec4(-0.32402530, -0.01591529, 0.600000, -1.543018), vec4(0.60771245, 0.41635221, 0.600000, -0.605411), vec4(0.02379565, -0.08239821, 0.600000, -3.809046), + vec4(0.48951152, -0.23657045, 0.600000, -1.189011), vec4(-0.17611565, -0.81696892, 0.600000, -0.513724), vec4(-0.33930185, -0.20732205, 0.600000, -1.698047), vec4(-0.91974425, 0.05403209, 0.600000, 0.062246), + vec4(-0.15064627, -0.14949332, 0.600000, -1.896062), vec4(0.53180975, -0.35210401, 0.600000, -0.758838), vec4(0.41487166, 0.81442589, 0.600000, -0.505648), vec4(-0.24106961, -0.32721516, 0.600000, -1.665244) +}; + +// these values can be changed (up to SSAO_MAX_TAPS) with no changes required elsewhere; values for 4th and 5th preset are ignored but array needed to avoid compilation errors +// the actual number of texture samples is two times this value (each "tap" has two symmetrical depth texture samples) +const int num_taps[5] = { 3, 5, 12, 0, 0 }; + +#define SSAO_TILT_SAMPLES_ENABLE_AT_QUALITY_PRESET (99) // to disable simply set to 99 or similar +#define SSAO_TILT_SAMPLES_AMOUNT (0.4) +// +#define SSAO_HALOING_REDUCTION_ENABLE_AT_QUALITY_PRESET (1) // to disable simply set to 99 or similar +#define SSAO_HALOING_REDUCTION_AMOUNT (0.6) // values from 0.0 - 1.0, 1.0 means max weighting (will cause artifacts, 0.8 is more reasonable) +// +#define SSAO_NORMAL_BASED_EDGES_ENABLE_AT_QUALITY_PRESET (2) // to disable simply set to 99 or similar +#define SSAO_NORMAL_BASED_EDGES_DOT_THRESHOLD (0.5) // use 0-0.1 for super-sharp normal-based edges +// +#define SSAO_DETAIL_AO_ENABLE_AT_QUALITY_PRESET (1) // whether to use detail; to disable simply set to 99 or similar +// +#define SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET (2) // !!warning!! the MIP generation on the C++ side will be enabled on quality preset 2 regardless of this value, so if changing here, change the C++ side too +#define SSAO_DEPTH_MIPS_GLOBAL_OFFSET (-4.3) // best noise/quality/performance tradeoff, found empirically +// +// !!warning!! the edge handling is hard-coded to 'disabled' on quality level 0, and enabled above, on the C++ side; while toggling it here will work for +// testing purposes, it will not yield performance gains (or correct results) +#define SSAO_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET (1) +// +#define SSAO_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET (1) + +#define SSAO_MAX_TAPS 32 +#define SSAO_MAX_REF_TAPS 512 +#define SSAO_ADAPTIVE_TAP_BASE_COUNT 5 +#define SSAO_ADAPTIVE_TAP_FLEXIBLE_COUNT (SSAO_MAX_TAPS - SSAO_ADAPTIVE_TAP_BASE_COUNT) +#define SSAO_DEPTH_MIP_LEVELS 4 + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(set = 0, binding = 0) uniform sampler2DArray source_depth_mipmaps; +layout(rgba8, set = 0, binding = 1) uniform restrict readonly image2D source_normal; +layout(set = 0, binding = 2) uniform Constants { //get into a lower set + vec4 rotation_matrices[20]; +} +constants; + +#ifdef ADAPTIVE +layout(rg8, set = 1, binding = 0) uniform restrict readonly image2DArray source_ssao; +layout(set = 1, binding = 1) uniform sampler2D source_importance; +layout(set = 1, binding = 2, std430) buffer Counter { + uint sum; +} +counter; +#endif + +layout(rg8, set = 2, binding = 0) uniform restrict writeonly image2D dest_image; + +// This push_constant is full - 128 bytes - if you need to add more data, consider adding to the uniform buffer instead +layout(push_constant, binding = 3, std430) uniform Params { + ivec2 screen_size; + int pass; + int quality; + + vec2 half_screen_pixel_size; + int size_multiplier; + float detail_intensity; + + vec2 NDC_to_view_mul; + vec2 NDC_to_view_add; + + vec2 pad2; + vec2 half_screen_pixel_size_x025; + + float radius; + float intensity; + float shadow_power; + float shadow_clamp; + + float fade_out_mul; + float fade_out_add; + float horizon_angle_threshold; + float inv_radius_near_limit; + + bool is_orthogonal; + float neg_inv_radius; + float load_counter_avg_div; + float adaptive_sample_limit; + + ivec2 pass_coord_offset; + vec2 pass_uv_offset; +} +params; + +// packing/unpacking for edges; 2 bits per edge mean 4 gradient values (0, 0.33, 0.66, 1) for smoother transitions! +float pack_edges(vec4 p_edgesLRTB) { + p_edgesLRTB = round(clamp(p_edgesLRTB, 0.0, 1.0) * 3.05); + return dot(p_edgesLRTB, vec4(64.0 / 255.0, 16.0 / 255.0, 4.0 / 255.0, 1.0 / 255.0)); +} + +vec3 NDC_to_view_space(vec2 p_pos, float p_viewspace_depth) { + if (params.is_orthogonal) { + return vec3((params.NDC_to_view_mul * p_pos.xy + params.NDC_to_view_add), p_viewspace_depth); + } else { + return vec3((params.NDC_to_view_mul * p_pos.xy + params.NDC_to_view_add) * p_viewspace_depth, p_viewspace_depth); + } +} + +// calculate effect radius and fit our screen sampling pattern inside it +void calculate_radius_parameters(const float p_pix_center_length, const vec2 p_pixel_size_at_center, out float r_lookup_radius, out float r_radius, out float r_fallof_sq) { + r_radius = params.radius; + + // when too close, on-screen sampling disk will grow beyond screen size; limit this to avoid closeup temporal artifacts + const float too_close_limit = clamp(p_pix_center_length * params.inv_radius_near_limit, 0.0, 1.0) * 0.8 + 0.2; + + r_radius *= too_close_limit; + + // 0.85 is to reduce the radius to allow for more samples on a slope to still stay within influence + r_lookup_radius = (0.85 * r_radius) / p_pixel_size_at_center.x; + + // used to calculate falloff (both for AO samples and per-sample weights) + r_fallof_sq = -1.0 / (r_radius * r_radius); +} + +vec4 calculate_edges(const float p_center_z, const float p_left_z, const float p_right_z, const float p_top_z, const float p_bottom_z) { + // slope-sensitive depth-based edge detection + vec4 edgesLRTB = vec4(p_left_z, p_right_z, p_top_z, p_bottom_z) - p_center_z; + vec4 edgesLRTB_slope_adjusted = edgesLRTB + edgesLRTB.yxwz; + edgesLRTB = min(abs(edgesLRTB), abs(edgesLRTB_slope_adjusted)); + return clamp((1.3 - edgesLRTB / (p_center_z * 0.040)), 0.0, 1.0); +} + +vec3 decode_normal(vec3 p_encoded_normal) { + vec3 normal = p_encoded_normal * 2.0 - 1.0; + return normal; +} + +vec3 load_normal(ivec2 p_pos) { + vec3 encoded_normal = imageLoad(source_normal, p_pos).xyz; + encoded_normal.z = 1.0 - encoded_normal.z; + return decode_normal(encoded_normal); +} + +vec3 load_normal(ivec2 p_pos, ivec2 p_offset) { + vec3 encoded_normal = imageLoad(source_normal, p_pos + p_offset).xyz; + encoded_normal.z = 1.0 - encoded_normal.z; + return decode_normal(encoded_normal); +} + +// all vectors in viewspace +float calculate_pixel_obscurance(vec3 p_pixel_normal, vec3 p_hit_delta, float p_fallof_sq) { + float length_sq = dot(p_hit_delta, p_hit_delta); + float NdotD = dot(p_pixel_normal, p_hit_delta) / sqrt(length_sq); + + float falloff_mult = max(0.0, length_sq * p_fallof_sq + 1.0); + + return max(0, NdotD - params.horizon_angle_threshold) * falloff_mult; +} + +void SSAO_tap_inner(const int p_quality_level, inout float r_obscurance_sum, inout float r_weight_sum, const vec2 p_sampling_uv, const float p_mip_level, const vec3 p_pix_center_pos, vec3 p_pixel_normal, const float p_fallof_sq, const float p_weight_mod) { + // get depth at sample + float viewspace_sample_z = textureLod(source_depth_mipmaps, vec3(p_sampling_uv, params.pass), p_mip_level).x; + + // convert to viewspace + vec3 hit_pos = NDC_to_view_space(p_sampling_uv.xy, viewspace_sample_z).xyz; + vec3 hit_delta = hit_pos - p_pix_center_pos; + + float obscurance = calculate_pixel_obscurance(p_pixel_normal, hit_delta, p_fallof_sq); + float weight = 1.0; + + if (p_quality_level >= SSAO_HALOING_REDUCTION_ENABLE_AT_QUALITY_PRESET) { + float reduct = max(0, -hit_delta.z); + reduct = clamp(reduct * params.neg_inv_radius + 2.0, 0.0, 1.0); + weight = SSAO_HALOING_REDUCTION_AMOUNT * reduct + (1.0 - SSAO_HALOING_REDUCTION_AMOUNT); + } + weight *= p_weight_mod; + r_obscurance_sum += obscurance * weight; + r_weight_sum += weight; +} + +void SSAOTap(const int p_quality_level, inout float r_obscurance_sum, inout float r_weight_sum, const int p_tap_index, const mat2 p_rot_scale, const vec3 p_pix_center_pos, vec3 p_pixel_normal, const vec2 p_normalized_screen_pos, const float p_mip_offset, const float p_fallof_sq, float p_weight_mod, vec2 p_norm_xy, float p_norm_xy_length) { + vec2 sample_offset; + float sample_pow_2_len; + + // patterns + { + vec4 new_sample = sample_pattern[p_tap_index]; + sample_offset = new_sample.xy * p_rot_scale; + sample_pow_2_len = new_sample.w; // precalculated, same as: sample_pow_2_len = log2( length( new_sample.xy ) ); + p_weight_mod *= new_sample.z; + } + + // snap to pixel center (more correct obscurance math, avoids artifacts) + sample_offset = round(sample_offset); + + // calculate MIP based on the sample distance from the centre, similar to as described + // in http://graphics.cs.williams.edu/papers/SAOHPG12/. + float mip_level = (p_quality_level < SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (sample_pow_2_len + p_mip_offset); + + vec2 sampling_uv = sample_offset * params.half_screen_pixel_size + p_normalized_screen_pos; + + SSAO_tap_inner(p_quality_level, r_obscurance_sum, r_weight_sum, sampling_uv, mip_level, p_pix_center_pos, p_pixel_normal, p_fallof_sq, p_weight_mod); + + // for the second tap, just use the mirrored offset + vec2 sample_offset_mirrored_uv = -sample_offset; + + // tilt the second set of samples so that the disk is effectively rotated by the normal + // effective at removing one set of artifacts, but too expensive for lower quality settings + if (p_quality_level >= SSAO_TILT_SAMPLES_ENABLE_AT_QUALITY_PRESET) { + float dot_norm = dot(sample_offset_mirrored_uv, p_norm_xy); + sample_offset_mirrored_uv -= dot_norm * p_norm_xy_length * p_norm_xy; + sample_offset_mirrored_uv = round(sample_offset_mirrored_uv); + } + + // snap to pixel center (more correct obscurance math, avoids artifacts) + vec2 sampling_mirrored_uv = sample_offset_mirrored_uv * params.half_screen_pixel_size + p_normalized_screen_pos; + + SSAO_tap_inner(p_quality_level, r_obscurance_sum, r_weight_sum, sampling_mirrored_uv, mip_level, p_pix_center_pos, p_pixel_normal, p_fallof_sq, p_weight_mod); +} + +void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, out float r_weight, const vec2 p_pos, int p_quality_level, bool p_adaptive_base) { + vec2 pos_rounded = trunc(p_pos); + uvec2 upos = uvec2(pos_rounded); + + const int number_of_taps = (p_adaptive_base) ? (SSAO_ADAPTIVE_TAP_BASE_COUNT) : (num_taps[p_quality_level]); + float pix_z, pix_left_z, pix_top_z, pix_right_z, pix_bottom_z; + + vec4 valuesUL = textureGather(source_depth_mipmaps, vec3(pos_rounded * params.half_screen_pixel_size, params.pass)); + vec4 valuesBR = textureGather(source_depth_mipmaps, vec3((pos_rounded + vec2(1.0)) * params.half_screen_pixel_size, params.pass)); + + // get this pixel's viewspace depth + pix_z = valuesUL.y; + + // get left right top bottom neighbouring pixels for edge detection (gets compiled out on quality_level == 0) + pix_left_z = valuesUL.x; + pix_top_z = valuesUL.z; + pix_right_z = valuesBR.z; + pix_bottom_z = valuesBR.x; + + vec2 normalized_screen_pos = pos_rounded * params.half_screen_pixel_size + params.half_screen_pixel_size_x025; + vec3 pix_center_pos = NDC_to_view_space(normalized_screen_pos, pix_z); + + // Load this pixel's viewspace normal + uvec2 full_res_coord = upos * 2 * params.size_multiplier + params.pass_coord_offset.xy; + vec3 pixel_normal = load_normal(ivec2(full_res_coord)); + + const vec2 pixel_size_at_center = NDC_to_view_space(normalized_screen_pos.xy + params.half_screen_pixel_size, pix_center_pos.z).xy - pix_center_pos.xy; + + float pixel_lookup_radius; + float fallof_sq; + + // calculate effect radius and fit our screen sampling pattern inside it + float viewspace_radius; + calculate_radius_parameters(length(pix_center_pos), pixel_size_at_center, pixel_lookup_radius, viewspace_radius, fallof_sq); + + // calculate samples rotation/scaling + mat2 rot_scale_matrix; + uint pseudo_random_index; + + { + vec4 rotation_scale; + // reduce effect radius near the screen edges slightly; ideally, one would render a larger depth buffer (5% on each side) instead + if (!p_adaptive_base && (p_quality_level >= SSAO_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET)) { + float near_screen_border = min(min(normalized_screen_pos.x, 1.0 - normalized_screen_pos.x), min(normalized_screen_pos.y, 1.0 - normalized_screen_pos.y)); + near_screen_border = clamp(10.0 * near_screen_border + 0.6, 0.0, 1.0); + pixel_lookup_radius *= near_screen_border; + } + + // load & update pseudo-random rotation matrix + pseudo_random_index = uint(pos_rounded.y * 2 + pos_rounded.x) % 5; + rotation_scale = constants.rotation_matrices[params.pass * 5 + pseudo_random_index]; + rot_scale_matrix = mat2(rotation_scale.x * pixel_lookup_radius, rotation_scale.y * pixel_lookup_radius, rotation_scale.z * pixel_lookup_radius, rotation_scale.w * pixel_lookup_radius); + } + + // the main obscurance & sample weight storage + float obscurance_sum = 0.0; + float weight_sum = 0.0; + + // edge mask for between this and left/right/top/bottom neighbour pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge) + vec4 edgesLRTB = vec4(1.0, 1.0, 1.0, 1.0); + + // Move center pixel slightly towards camera to avoid imprecision artifacts due to using of 16bit depth buffer; a lot smaller offsets needed when using 32bit floats + pix_center_pos *= 0.9992; + + if (!p_adaptive_base && (p_quality_level >= SSAO_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET)) { + edgesLRTB = calculate_edges(pix_z, pix_left_z, pix_right_z, pix_top_z, pix_bottom_z); + } + + // adds a more high definition sharp effect, which gets blurred out (reuses left/right/top/bottom samples that we used for edge detection) + if (!p_adaptive_base && (p_quality_level >= SSAO_DETAIL_AO_ENABLE_AT_QUALITY_PRESET)) { + // disable in case of quality level 4 (reference) + if (p_quality_level != 4) { + //approximate neighbouring pixels positions (actually just deltas or "positions - pix_center_pos" ) + vec3 normalized_viewspace_dir = vec3(pix_center_pos.xy / pix_center_pos.zz, 1.0); + vec3 pixel_left_delta = vec3(-pixel_size_at_center.x, 0.0, 0.0) + normalized_viewspace_dir * (pix_left_z - pix_center_pos.z); + vec3 pixel_right_delta = vec3(+pixel_size_at_center.x, 0.0, 0.0) + normalized_viewspace_dir * (pix_right_z - pix_center_pos.z); + vec3 pixel_top_delta = vec3(0.0, -pixel_size_at_center.y, 0.0) + normalized_viewspace_dir * (pix_top_z - pix_center_pos.z); + vec3 pixel_bottom_delta = vec3(0.0, +pixel_size_at_center.y, 0.0) + normalized_viewspace_dir * (pix_bottom_z - pix_center_pos.z); + + const float range_reduction = 4.0f; // this is to avoid various artifacts + const float modified_fallof_sq = range_reduction * fallof_sq; + + vec4 additional_obscurance; + additional_obscurance.x = calculate_pixel_obscurance(pixel_normal, pixel_left_delta, modified_fallof_sq); + additional_obscurance.y = calculate_pixel_obscurance(pixel_normal, pixel_right_delta, modified_fallof_sq); + additional_obscurance.z = calculate_pixel_obscurance(pixel_normal, pixel_top_delta, modified_fallof_sq); + additional_obscurance.w = calculate_pixel_obscurance(pixel_normal, pixel_bottom_delta, modified_fallof_sq); + + obscurance_sum += params.detail_intensity * dot(additional_obscurance, edgesLRTB); + } + } + + // Sharp normals also create edges - but this adds to the cost as well + if (!p_adaptive_base && (p_quality_level >= SSAO_NORMAL_BASED_EDGES_ENABLE_AT_QUALITY_PRESET)) { + vec3 neighbour_normal_left = load_normal(ivec2(full_res_coord), ivec2(-2, 0)); + vec3 neighbour_normal_right = load_normal(ivec2(full_res_coord), ivec2(2, 0)); + vec3 neighbour_normal_top = load_normal(ivec2(full_res_coord), ivec2(0, -2)); + vec3 neighbour_normal_bottom = load_normal(ivec2(full_res_coord), ivec2(0, 2)); + + const float dot_threshold = SSAO_NORMAL_BASED_EDGES_DOT_THRESHOLD; + + vec4 normal_edgesLRTB; + normal_edgesLRTB.x = clamp((dot(pixel_normal, neighbour_normal_left) + dot_threshold), 0.0, 1.0); + normal_edgesLRTB.y = clamp((dot(pixel_normal, neighbour_normal_right) + dot_threshold), 0.0, 1.0); + normal_edgesLRTB.z = clamp((dot(pixel_normal, neighbour_normal_top) + dot_threshold), 0.0, 1.0); + normal_edgesLRTB.w = clamp((dot(pixel_normal, neighbour_normal_bottom) + dot_threshold), 0.0, 1.0); + + edgesLRTB *= normal_edgesLRTB; + } + + const float global_mip_offset = SSAO_DEPTH_MIPS_GLOBAL_OFFSET; + float mip_offset = (p_quality_level < SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (log2(pixel_lookup_radius) + global_mip_offset); + + // Used to tilt the second set of samples so that the disk is effectively rotated by the normal + // effective at removing one set of artifacts, but too expensive for lower quality settings + vec2 norm_xy = vec2(pixel_normal.x, pixel_normal.y); + float norm_xy_length = length(norm_xy); + norm_xy /= vec2(norm_xy_length, -norm_xy_length); + norm_xy_length *= SSAO_TILT_SAMPLES_AMOUNT; + + // standard, non-adaptive approach + if ((p_quality_level != 3) || p_adaptive_base) { + for (int i = 0; i < number_of_taps; i++) { + SSAOTap(p_quality_level, obscurance_sum, weight_sum, i, rot_scale_matrix, pix_center_pos, pixel_normal, normalized_screen_pos, mip_offset, fallof_sq, 1.0, norm_xy, norm_xy_length); + } + } +#ifdef ADAPTIVE + else { + // add new ones if needed + vec2 full_res_uv = normalized_screen_pos + params.pass_uv_offset.xy; + float importance = textureLod(source_importance, full_res_uv, 0.0).x; + + // this is to normalize SSAO_DETAIL_AO_AMOUNT across all pixel regardless of importance + obscurance_sum *= (SSAO_ADAPTIVE_TAP_BASE_COUNT / float(SSAO_MAX_TAPS)) + (importance * SSAO_ADAPTIVE_TAP_FLEXIBLE_COUNT / float(SSAO_MAX_TAPS)); + + // load existing base values + vec2 base_values = imageLoad(source_ssao, ivec3(upos, params.pass)).xy; + weight_sum += base_values.y * float(SSAO_ADAPTIVE_TAP_BASE_COUNT * 4.0); + obscurance_sum += (base_values.x) * weight_sum; + + // increase importance around edges + float edge_count = dot(1.0 - edgesLRTB, vec4(1.0, 1.0, 1.0, 1.0)); + + float avg_total_importance = float(counter.sum) * params.load_counter_avg_div; + + float importance_limiter = clamp(params.adaptive_sample_limit / avg_total_importance, 0.0, 1.0); + importance *= importance_limiter; + + float additional_sample_count = SSAO_ADAPTIVE_TAP_FLEXIBLE_COUNT * importance; + + const float blend_range = 3.0; + const float blend_range_inv = 1.0 / blend_range; + + additional_sample_count += 0.5; + uint additional_samples = uint(additional_sample_count); + uint additional_samples_to = min(SSAO_MAX_TAPS, additional_samples + SSAO_ADAPTIVE_TAP_BASE_COUNT); + + for (uint i = SSAO_ADAPTIVE_TAP_BASE_COUNT; i < additional_samples_to; i++) { + additional_sample_count -= 1.0f; + float weight_mod = clamp(additional_sample_count * blend_range_inv, 0.0, 1.0); + SSAOTap(p_quality_level, obscurance_sum, weight_sum, int(i), rot_scale_matrix, pix_center_pos, pixel_normal, normalized_screen_pos, mip_offset, fallof_sq, weight_mod, norm_xy, norm_xy_length); + } + } +#endif + + // early out for adaptive base - just output weight (used for the next pass) + if (p_adaptive_base) { + float obscurance = obscurance_sum / weight_sum; + + r_shadow_term = obscurance; + r_edges = vec4(0.0); + r_weight = weight_sum; + return; + } + + // calculate weighted average + float obscurance = obscurance_sum / weight_sum; + + // calculate fadeout (1 close, gradient, 0 far) + float fade_out = clamp(pix_center_pos.z * params.fade_out_mul + params.fade_out_add, 0.0, 1.0); + + // Reduce the SSAO shadowing if we're on the edge to remove artifacts on edges (we don't care for the lower quality one) + if (!p_adaptive_base && (p_quality_level >= SSAO_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET)) { + // when there's more than 2 opposite edges, start fading out the occlusion to reduce aliasing artifacts + float edge_fadeout_factor = clamp((1.0 - edgesLRTB.x - edgesLRTB.y) * 0.35, 0.0, 1.0) + clamp((1.0 - edgesLRTB.z - edgesLRTB.w) * 0.35, 0.0, 1.0); + + fade_out *= clamp(1.0 - edge_fadeout_factor, 0.0, 1.0); + } + + // strength + obscurance = params.intensity * obscurance; + + // clamp + obscurance = min(obscurance, params.shadow_clamp); + + // fadeout + obscurance *= fade_out; + + // conceptually switch to occlusion with the meaning being visibility (grows with visibility, occlusion == 1 implies full visibility), + // to be in line with what is more commonly used. + float occlusion = 1.0 - obscurance; + + // modify the gradient + // note: this cannot be moved to a later pass because of loss of precision after storing in the render target + occlusion = pow(clamp(occlusion, 0.0, 1.0), params.shadow_power); + + // outputs! + r_shadow_term = occlusion; // Our final 'occlusion' term (0 means fully occluded, 1 means fully lit) + r_edges = edgesLRTB; // These are used to prevent blurring across edges, 1 means no edge, 0 means edge, 0.5 means half way there, etc. + r_weight = weight_sum; +} + +void main() { + float out_shadow_term; + float out_weight; + vec4 out_edges; + ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing + return; + } + + vec2 uv = vec2(gl_GlobalInvocationID) + vec2(0.5); +#ifdef SSAO_BASE + generate_SSAO_shadows_internal(out_shadow_term, out_edges, out_weight, uv, params.quality, true); + + imageStore(dest_image, ivec2(gl_GlobalInvocationID.xy), vec4(out_shadow_term, out_weight / (float(SSAO_ADAPTIVE_TAP_BASE_COUNT) * 4.0), 0.0, 0.0)); +#else + generate_SSAO_shadows_internal(out_shadow_term, out_edges, out_weight, uv, params.quality, false); // pass in quality levels + if (params.quality == 0) { + out_edges = vec4(1.0); + } + + imageStore(dest_image, ivec2(gl_GlobalInvocationID.xy), vec4(out_shadow_term, pack_edges(out_edges), 0.0, 0.0)); +#endif +} diff --git a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl b/servers/rendering/renderer_rd/shaders/ssao_blur.glsl new file mode 100644 index 0000000000..510a777048 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/ssao_blur.glsl @@ -0,0 +1,154 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016, Intel Corporation +// 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. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// File changes (yyyy-mm-dd) +// 2016-09-07: filip.strugar@intel.com: first commit +// 2020-12-05: clayjohn: convert to Vulkan and Godot +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(set = 0, binding = 0) uniform sampler2D source_ssao; + +layout(rg8, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; + +layout(push_constant, binding = 1, std430) uniform Params { + float edge_sharpness; + float pad; + vec2 half_screen_pixel_size; +} +params; + +vec4 unpack_edges(float p_packed_val) { + uint packed_val = uint(p_packed_val * 255.5); + vec4 edgesLRTB; + edgesLRTB.x = float((packed_val >> 6) & 0x03) / 3.0; + edgesLRTB.y = float((packed_val >> 4) & 0x03) / 3.0; + edgesLRTB.z = float((packed_val >> 2) & 0x03) / 3.0; + edgesLRTB.w = float((packed_val >> 0) & 0x03) / 3.0; + + return clamp(edgesLRTB + params.edge_sharpness, 0.0, 1.0); +} + +void add_sample(float p_ssao_value, float p_edge_value, inout float r_sum, inout float r_sum_weight) { + float weight = p_edge_value; + + r_sum += (weight * p_ssao_value); + r_sum_weight += weight; +} + +#ifdef MODE_WIDE +vec2 sample_blurred_wide(vec2 p_coord) { + vec2 vC = textureLodOffset(source_ssao, vec2(p_coord), 0.0, ivec2(0, 0)).xy; + vec2 vL = textureLodOffset(source_ssao, vec2(p_coord), 0.0, ivec2(-2, 0)).xy; + vec2 vT = textureLodOffset(source_ssao, vec2(p_coord), 0.0, ivec2(0, -2)).xy; + vec2 vR = textureLodOffset(source_ssao, vec2(p_coord), 0.0, ivec2(2, 0)).xy; + vec2 vB = textureLodOffset(source_ssao, vec2(p_coord), 0.0, ivec2(0, 2)).xy; + + float packed_edges = vC.y; + vec4 edgesLRTB = unpack_edges(packed_edges); + edgesLRTB.x *= unpack_edges(vL.y).y; + edgesLRTB.z *= unpack_edges(vT.y).w; + edgesLRTB.y *= unpack_edges(vR.y).x; + edgesLRTB.w *= unpack_edges(vB.y).z; + + float ssao_value = vC.x; + float ssao_valueL = vL.x; + float ssao_valueT = vT.x; + float ssao_valueR = vR.x; + float ssao_valueB = vB.x; + + float sum_weight = 0.8f; + float sum = ssao_value * sum_weight; + + add_sample(ssao_valueL, edgesLRTB.x, sum, sum_weight); + add_sample(ssao_valueR, edgesLRTB.y, sum, sum_weight); + add_sample(ssao_valueT, edgesLRTB.z, sum, sum_weight); + add_sample(ssao_valueB, edgesLRTB.w, sum, sum_weight); + + float ssao_avg = sum / sum_weight; + + ssao_value = ssao_avg; + + return vec2(ssao_value, packed_edges); +} +#endif + +#ifdef MODE_SMART +vec2 sample_blurred(vec3 p_pos, vec2 p_coord) { + float packed_edges = texelFetch(source_ssao, ivec2(p_pos.xy), 0).y; + vec4 edgesLRTB = unpack_edges(packed_edges); + + vec4 valuesUL = textureGather(source_ssao, vec2(p_coord - params.half_screen_pixel_size * 0.5)); + vec4 valuesBR = textureGather(source_ssao, vec2(p_coord + params.half_screen_pixel_size * 0.5)); + + float ssao_value = valuesUL.y; + float ssao_valueL = valuesUL.x; + float ssao_valueT = valuesUL.z; + float ssao_valueR = valuesBR.z; + float ssao_valueB = valuesBR.x; + + float sum_weight = 0.5; + float sum = ssao_value * sum_weight; + + add_sample(ssao_valueL, edgesLRTB.x, sum, sum_weight); + add_sample(ssao_valueR, edgesLRTB.y, sum, sum_weight); + + add_sample(ssao_valueT, edgesLRTB.z, sum, sum_weight); + add_sample(ssao_valueB, edgesLRTB.w, sum, sum_weight); + + float ssao_avg = sum / sum_weight; + + ssao_value = ssao_avg; + + return vec2(ssao_value, packed_edges); +} +#endif + +void main() { + // Pixel being shaded + ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); + +#ifdef MODE_NON_SMART + + vec2 halfPixel = params.half_screen_pixel_size * 0.5f; + + vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size; + + vec2 centre = textureLod(source_ssao, vec2(uv), 0.0).xy; + + vec4 vals; + vals.x = textureLod(source_ssao, vec2(uv + vec2(-halfPixel.x * 3, -halfPixel.y)), 0.0).x; + vals.y = textureLod(source_ssao, vec2(uv + vec2(+halfPixel.x, -halfPixel.y * 3)), 0.0).x; + vals.z = textureLod(source_ssao, vec2(uv + vec2(-halfPixel.x, +halfPixel.y * 3)), 0.0).x; + vals.w = textureLod(source_ssao, vec2(uv + vec2(+halfPixel.x * 3, +halfPixel.y)), 0.0).x; + + vec2 sampled = vec2(dot(vals, vec4(0.2)) + centre.x * 0.2, centre.y); + +#else +#ifdef MODE_SMART + vec2 sampled = sample_blurred(vec3(gl_GlobalInvocationID), (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size); +#else // MODE_WIDE + vec2 sampled = sample_blurred_wide((vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size); +#endif + +#endif + imageStore(dest_image, ivec2(ssC), vec4(sampled, 0.0, 0.0)); +} diff --git a/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl b/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl new file mode 100644 index 0000000000..cb2d31f70d --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl @@ -0,0 +1,206 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016, Intel Corporation +// 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. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// File changes (yyyy-mm-dd) +// 2016-09-07: filip.strugar@intel.com: first commit +// 2020-12-05: clayjohn: convert to Vulkan and Godot +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(push_constant, binding = 1, std430) uniform Params { + vec2 pixel_size; + float z_far; + float z_near; + bool orthogonal; + float radius_sq; + uvec2 pad; +} +params; + +layout(set = 0, binding = 0) uniform sampler2D source_depth; + +layout(r16f, set = 1, binding = 0) uniform restrict writeonly image2DArray dest_image0; //rename +#ifdef GENERATE_MIPS +layout(r16f, set = 2, binding = 0) uniform restrict writeonly image2DArray dest_image1; +layout(r16f, set = 2, binding = 1) uniform restrict writeonly image2DArray dest_image2; +layout(r16f, set = 2, binding = 2) uniform restrict writeonly image2DArray dest_image3; +#endif + +vec4 screen_space_to_view_space_depth(vec4 p_depth) { + if (params.orthogonal) { + vec4 depth = p_depth * 2.0 - 1.0; + return ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } + + float depth_linearize_mul = params.z_near; + float depth_linearize_add = params.z_far; + + // Optimised version of "-cameraClipNear / (cameraClipFar - projDepth * (cameraClipFar - cameraClipNear)) * cameraClipFar" + + // Set your depth_linearize_mul and depth_linearize_add to: + // depth_linearize_mul = ( cameraClipFar * cameraClipNear) / ( cameraClipFar - cameraClipNear ); + // depth_linearize_add = cameraClipFar / ( cameraClipFar - cameraClipNear ); + + return depth_linearize_mul / (depth_linearize_add - p_depth); +} + +float screen_space_to_view_space_depth(float p_depth) { + if (params.orthogonal) { + float depth = p_depth * 2.0 - 1.0; + return ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / (2.0 * params.z_far); + } + + float depth_linearize_mul = params.z_near; + float depth_linearize_add = params.z_far; + + return depth_linearize_mul / (depth_linearize_add - p_depth); +} + +#ifdef GENERATE_MIPS + +shared float depth_buffer[4][8][8]; + +float mip_smart_average(vec4 p_depths) { + float closest = min(min(p_depths.x, p_depths.y), min(p_depths.z, p_depths.w)); + float fallof_sq = -1.0f / params.radius_sq; + vec4 dists = p_depths - closest.xxxx; + vec4 weights = clamp(dists * dists * fallof_sq + 1.0, 0.0, 1.0); + return dot(weights, p_depths) / dot(weights, vec4(1.0, 1.0, 1.0, 1.0)); +} + +void prepare_depths_and_mips(vec4 p_samples, uvec2 p_output_coord, uvec2 p_gtid) { + p_samples = screen_space_to_view_space_depth(p_samples); + + depth_buffer[0][p_gtid.x][p_gtid.y] = p_samples.w; + depth_buffer[1][p_gtid.x][p_gtid.y] = p_samples.z; + depth_buffer[2][p_gtid.x][p_gtid.y] = p_samples.x; + depth_buffer[3][p_gtid.x][p_gtid.y] = p_samples.y; + + imageStore(dest_image0, ivec3(p_output_coord.x, p_output_coord.y, 0), vec4(p_samples.w)); + imageStore(dest_image0, ivec3(p_output_coord.x, p_output_coord.y, 1), vec4(p_samples.z)); + imageStore(dest_image0, ivec3(p_output_coord.x, p_output_coord.y, 2), vec4(p_samples.x)); + imageStore(dest_image0, ivec3(p_output_coord.x, p_output_coord.y, 3), vec4(p_samples.y)); + + uint depth_array_index = 2 * (p_gtid.y % 2) + (p_gtid.x % 2); + uvec2 depth_array_offset = ivec2(p_gtid.x % 2, p_gtid.y % 2); + ivec2 buffer_coord = ivec2(p_gtid) - ivec2(depth_array_offset); + + p_output_coord /= 2; + groupMemoryBarrier(); + barrier(); + + // if (still_alive) <-- all threads alive here + { + float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0]; + float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 1]; + float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 1][buffer_coord.y + 0]; + float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 1][buffer_coord.y + 1]; + + float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11)); + imageStore(dest_image1, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg)); + depth_buffer[depth_array_index][buffer_coord.x][buffer_coord.y] = avg; + } + + bool still_alive = p_gtid.x % 4 == depth_array_offset.x && p_gtid.y % 4 == depth_array_offset.y; + + p_output_coord /= 2; + groupMemoryBarrier(); + barrier(); + + if (still_alive) { + float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0]; + float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 2]; + float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 2][buffer_coord.y + 0]; + float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 2][buffer_coord.y + 2]; + + float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11)); + imageStore(dest_image2, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg)); + depth_buffer[depth_array_index][buffer_coord.x][buffer_coord.y] = avg; + } + + still_alive = p_gtid.x % 8 == depth_array_offset.x && depth_array_offset.y % 8 == depth_array_offset.y; + + p_output_coord /= 2; + groupMemoryBarrier(); + barrier(); + + if (still_alive) { + float sample_00 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 0]; + float sample_01 = depth_buffer[depth_array_index][buffer_coord.x + 0][buffer_coord.y + 4]; + float sample_10 = depth_buffer[depth_array_index][buffer_coord.x + 4][buffer_coord.y + 0]; + float sample_11 = depth_buffer[depth_array_index][buffer_coord.x + 4][buffer_coord.y + 4]; + + float avg = mip_smart_average(vec4(sample_00, sample_01, sample_10, sample_11)); + imageStore(dest_image3, ivec3(p_output_coord.x, p_output_coord.y, depth_array_index), vec4(avg)); + } +} +#else +#ifndef USE_HALF_BUFFERS +void prepare_depths(vec4 p_samples, uvec2 p_tid) { + p_samples = screen_space_to_view_space_depth(p_samples); + + imageStore(dest_image0, ivec3(p_tid, 0), vec4(p_samples.w)); + imageStore(dest_image0, ivec3(p_tid, 1), vec4(p_samples.z)); + imageStore(dest_image0, ivec3(p_tid, 2), vec4(p_samples.x)); + imageStore(dest_image0, ivec3(p_tid, 3), vec4(p_samples.y)); +} +#endif +#endif + +void main() { +#ifdef USE_HALF_BUFFERS +#ifdef USE_HALF_SIZE + float sample_00 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 0, 4 * gl_GlobalInvocationID.y + 0), 0).x; + float sample_11 = texelFetch(source_depth, ivec2(4 * gl_GlobalInvocationID.x + 2, 4 * gl_GlobalInvocationID.y + 2), 0).x; +#else + float sample_00 = texelFetch(source_depth, ivec2(2 * gl_GlobalInvocationID.x + 0, 2 * gl_GlobalInvocationID.y + 0), 0).x; + float sample_11 = texelFetch(source_depth, ivec2(2 * gl_GlobalInvocationID.x + 1, 2 * gl_GlobalInvocationID.y + 1), 0).x; +#endif + sample_00 = screen_space_to_view_space_depth(sample_00); + sample_11 = screen_space_to_view_space_depth(sample_11); + + imageStore(dest_image0, ivec3(gl_GlobalInvocationID.xy, 0), vec4(sample_00)); + imageStore(dest_image0, ivec3(gl_GlobalInvocationID.xy, 3), vec4(sample_11)); +#else //!USE_HALF_BUFFERS +#ifdef USE_HALF_SIZE + ivec2 depth_buffer_coord = 4 * ivec2(gl_GlobalInvocationID.xy); + ivec2 output_coord = ivec2(gl_GlobalInvocationID); + + vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size; + vec4 samples; + samples.x = textureLodOffset(source_depth, uv, 0, ivec2(0, 2)).x; + samples.y = textureLodOffset(source_depth, uv, 0, ivec2(2, 2)).x; + samples.z = textureLodOffset(source_depth, uv, 0, ivec2(2, 0)).x; + samples.w = textureLodOffset(source_depth, uv, 0, ivec2(0, 0)).x; +#else + ivec2 depth_buffer_coord = 2 * ivec2(gl_GlobalInvocationID.xy); + ivec2 output_coord = ivec2(gl_GlobalInvocationID); + + vec2 uv = (vec2(depth_buffer_coord) + 0.5f) * params.pixel_size; + vec4 samples = textureGather(source_depth, uv); +#endif +#ifdef GENERATE_MIPS + prepare_depths_and_mips(samples, output_coord, gl_LocalInvocationID.xy); +#else + prepare_depths(samples, gl_GlobalInvocationID.xy); +#endif +#endif +} diff --git a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl new file mode 100644 index 0000000000..6aa7624261 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl @@ -0,0 +1,126 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016, Intel Corporation +// 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. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// File changes (yyyy-mm-dd) +// 2016-09-07: filip.strugar@intel.com: first commit +// 2020-12-05: clayjohn: convert to Vulkan and Godot +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#ifdef GENERATE_MAP +layout(set = 0, binding = 0) uniform sampler2DArray source_ssao; +#else +layout(set = 0, binding = 0) uniform sampler2D source_importance; +#endif +layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; + +#ifdef PROCESS_MAPB +layout(set = 2, binding = 0, std430) buffer Counter { + uint sum; +} +counter; +#endif + +layout(push_constant, binding = 1, std430) uniform Params { + vec2 half_screen_pixel_size; + float intensity; + float power; +} +params; + +void main() { + // Pixel being shaded + ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); + +#ifdef GENERATE_MAP + // importance map stuff + uvec2 base_position = ssC * 2; + + vec2 base_uv = (vec2(base_position) + vec2(0.5f, 0.5f)) * params.half_screen_pixel_size; + + float avg = 0.0; + float minV = 1.0; + float maxV = 0.0; + for (int i = 0; i < 4; i++) { + vec4 vals = textureGather(source_ssao, vec3(base_uv, i)); + + // apply the same modifications that would have been applied in the main shader + vals = params.intensity * vals; + + vals = 1 - vals; + + vals = pow(clamp(vals, 0.0, 1.0), vec4(params.power)); + + avg += dot(vec4(vals.x, vals.y, vals.z, vals.w), vec4(1.0 / 16.0, 1.0 / 16.0, 1.0 / 16.0, 1.0 / 16.0)); + + maxV = max(maxV, max(max(vals.x, vals.y), max(vals.z, vals.w))); + minV = min(minV, min(min(vals.x, vals.y), min(vals.z, vals.w))); + } + + float min_max_diff = maxV - minV; + + imageStore(dest_image, ssC, vec4(pow(clamp(min_max_diff * 2.0, 0.0, 1.0), 0.8))); +#endif + +#ifdef PROCESS_MAPA + vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0; + + float centre = textureLod(source_importance, uv, 0.0).x; + + vec2 half_pixel = params.half_screen_pixel_size; + + vec4 vals; + vals.x = textureLod(source_importance, uv + vec2(-half_pixel.x * 3, -half_pixel.y), 0.0).x; + vals.y = textureLod(source_importance, uv + vec2(+half_pixel.x, -half_pixel.y * 3), 0.0).x; + vals.z = textureLod(source_importance, uv + vec2(+half_pixel.x * 3, +half_pixel.y), 0.0).x; + vals.w = textureLod(source_importance, uv + vec2(-half_pixel.x, +half_pixel.y * 3), 0.0).x; + + float avg = dot(vals, vec4(0.25, 0.25, 0.25, 0.25)); + + imageStore(dest_image, ssC, vec4(avg)); +#endif + +#ifdef PROCESS_MAPB + vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0; + + float centre = textureLod(source_importance, uv, 0.0).x; + + vec2 half_pixel = params.half_screen_pixel_size; + + vec4 vals; + vals.x = textureLod(source_importance, uv + vec2(-half_pixel.x, -half_pixel.y * 3), 0.0).x; + vals.y = textureLod(source_importance, uv + vec2(+half_pixel.x * 3, -half_pixel.y), 0.0).x; + vals.z = textureLod(source_importance, uv + vec2(+half_pixel.x, +half_pixel.y * 3), 0.0).x; + vals.w = textureLod(source_importance, uv + vec2(-half_pixel.x * 3, +half_pixel.y), 0.0).x; + + float avg = dot(vals, vec4(0.25, 0.25, 0.25, 0.25)); + + imageStore(dest_image, ssC, vec4(avg)); + + // sum the average; to avoid overflowing we assume max AO resolution is not bigger than 16384x16384; so quarter res (used here) will be 4096x4096, which leaves us with 8 bits per pixel + uint sum = uint(clamp(avg, 0.0, 1.0) * 255.0 + 0.5); + + // save every 9th to avoid InterlockedAdd congestion - since we're blurring, this is good enough; compensated by multiplying load_counter_avg_div by 9 + if (((ssC.x % 3) + (ssC.y % 3)) == 0) { + atomicAdd(counter.sum, sum); + } +#endif +} diff --git a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl new file mode 100644 index 0000000000..4fdf334aa5 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl @@ -0,0 +1,119 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016, Intel Corporation +// 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. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// File changes (yyyy-mm-dd) +// 2016-09-07: filip.strugar@intel.com: first commit +// 2020-12-05: clayjohn: convert to Vulkan and Godot +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout(rgba8, set = 0, binding = 0) uniform restrict writeonly image2D dest_image; +layout(set = 1, binding = 0) uniform sampler2DArray source_texture; + +layout(push_constant, binding = 1, std430) uniform Params { + float inv_sharpness; + uint size_modifier; + vec2 pixel_size; +} +params; + +vec4 unpack_edges(float p_packed_val) { + uint packed_val = uint(p_packed_val * 255.5); + vec4 edgesLRTB; + edgesLRTB.x = float((packed_val >> 6) & 0x03) / 3.0; + edgesLRTB.y = float((packed_val >> 4) & 0x03) / 3.0; + edgesLRTB.z = float((packed_val >> 2) & 0x03) / 3.0; + edgesLRTB.w = float((packed_val >> 0) & 0x03) / 3.0; + + return clamp(edgesLRTB + params.inv_sharpness, 0.0, 1.0); +} + +void main() { + ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(ssC, ivec2(1.0 / params.pixel_size)))) { //too large, do nothing + return; + } + +#ifdef MODE_SMART + float ao; + uvec2 pix_pos = uvec2(gl_GlobalInvocationID.xy); + vec2 uv = (gl_GlobalInvocationID.xy + vec2(0.5)) * params.pixel_size; + + // calculate index in the four deinterleaved source array texture + int mx = int(pix_pos.x % 2); + int my = int(pix_pos.y % 2); + int index_center = mx + my * 2; // center index + int index_horizontal = (1 - mx) + my * 2; // neighbouring, horizontal + int index_vertical = mx + (1 - my) * 2; // neighbouring, vertical + int index_diagonal = (1 - mx) + (1 - my) * 2; // diagonal + + vec2 center_val = texelFetch(source_texture, ivec3(pix_pos / uvec2(params.size_modifier), index_center), 0).xy; + + ao = center_val.x; + + vec4 edgesLRTB = unpack_edges(center_val.y); + + // convert index shifts to sampling offsets + float fmx = float(mx); + float fmy = float(my); + + // in case of an edge, push sampling offsets away from the edge (towards pixel center) + float fmxe = (edgesLRTB.y - edgesLRTB.x); + float fmye = (edgesLRTB.w - edgesLRTB.z); + + // calculate final sampling offsets and sample using bilinear filter + vec2 uv_horizontal = (gl_GlobalInvocationID.xy + vec2(0.5) + vec2(fmx + fmxe - 0.5, 0.5 - fmy)) * params.pixel_size; + float ao_horizontal = textureLod(source_texture, vec3(uv_horizontal, index_horizontal), 0.0).x; + vec2 uv_vertical = (gl_GlobalInvocationID.xy + vec2(0.5) + vec2(0.5 - fmx, fmy - 0.5 + fmye)) * params.pixel_size; + float ao_vertical = textureLod(source_texture, vec3(uv_vertical, index_vertical), 0.0).x; + vec2 uv_diagonal = (gl_GlobalInvocationID.xy + vec2(0.5) + vec2(fmx - 0.5 + fmxe, fmy - 0.5 + fmye)) * params.pixel_size; + float ao_diagonal = textureLod(source_texture, vec3(uv_diagonal, index_diagonal), 0.0).x; + + // reduce weight for samples near edge - if the edge is on both sides, weight goes to 0 + vec4 blendWeights; + blendWeights.x = 1.0; + blendWeights.y = (edgesLRTB.x + edgesLRTB.y) * 0.5; + blendWeights.z = (edgesLRTB.z + edgesLRTB.w) * 0.5; + blendWeights.w = (blendWeights.y + blendWeights.z) * 0.5; + + // calculate weighted average + float blendWeightsSum = dot(blendWeights, vec4(1.0, 1.0, 1.0, 1.0)); + ao = dot(vec4(ao, ao_horizontal, ao_vertical, ao_diagonal), blendWeights) / blendWeightsSum; + + imageStore(dest_image, ivec2(gl_GlobalInvocationID.xy), vec4(ao)); +#else // !MODE_SMART + + vec2 uv = (gl_GlobalInvocationID.xy + vec2(0.5)) * params.pixel_size; +#ifdef MODE_HALF + float a = textureLod(source_texture, vec3(uv, 0), 0.0).x; + float d = textureLod(source_texture, vec3(uv, 3), 0.0).x; + float avg = (a + d) * 0.5; + +#else + float a = textureLod(source_texture, vec3(uv, 0), 0.0).x; + float b = textureLod(source_texture, vec3(uv, 1), 0.0).x; + float c = textureLod(source_texture, vec3(uv, 2), 0.0).x; + float d = textureLod(source_texture, vec3(uv, 3), 0.0).x; + float avg = (a + b + c + d) * 0.25; + +#endif + imageStore(dest_image, ivec2(gl_GlobalInvocationID.xy), vec4(avg)); +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl index 88a953562f..88a953562f 100644 --- a/servers/rendering/rasterizer_rd/shaders/subsurface_scattering.glsl +++ b/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl index 4cc4fd3f64..7de91fd541 100644 --- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl +++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl @@ -23,7 +23,11 @@ layout(location = 0) in vec2 uv_interp; layout(set = 0, binding = 0) uniform sampler2D source_color; layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; layout(set = 2, binding = 0) uniform sampler2D source_glow; -layout(set = 3, binding = 0) uniform sampler3D color_correction; +#ifdef USE_1D_LUT +layout(set = 3, binding = 0) uniform sampler2D source_color_correction; +#else +layout(set = 3, binding = 0) uniform sampler3D source_color_correction; +#endif layout(push_constant, binding = 1, std430) uniform Params { vec3 bcs; @@ -35,9 +39,9 @@ layout(push_constant, binding = 1, std430) uniform Params { uint tonemapper; uvec2 glow_texture_size; - float glow_intensity; uint pad3; + uint glow_mode; float glow_levels[7]; @@ -255,10 +259,18 @@ vec3 apply_bcs(vec3 color, vec3 bcs) { return color; } - -vec3 apply_color_correction(vec3 color, sampler3D correction_tex) { - return texture(correction_tex, color).rgb; +#ifdef USE_1D_LUT +vec3 apply_color_correction(vec3 color) { + color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r; + color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g; + color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b; + return color; +} +#else +vec3 apply_color_correction(vec3 color) { + return textureLod(source_color_correction, color, 0.0).rgb; } +#endif vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) { const float FXAA_REDUCE_MIN = (1.0 / 128.0); @@ -367,7 +379,7 @@ void main() { } if (params.use_color_correction) { - color = apply_color_correction(color, color_correction); + color = apply_color_correction(color); } frag_color = vec4(color, 1.0f); diff --git a/servers/rendering/rasterizer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl index 13b162f0c9..498a6ddb5b 100644 --- a/servers/rendering/rasterizer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl @@ -169,6 +169,15 @@ vec3 hash3f(uvec3 x) { return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF)); } +float get_omni_attenuation(float distance, float inv_range, float decay) { + float nd = distance * inv_range; + nd *= nd; + nd *= nd; // nd^4 + nd = max(1.0 - nd, 0.0); + nd *= nd; // nd^2 + return nd * pow(max(distance, 0.0001), -decay); +} + void main() { vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size); @@ -270,14 +279,14 @@ void main() { uint light_index = cluster_data.indices[omni_light_pointer + i]; vec3 light_pos = lights.data[i].position; - float d = distance(lights.data[i].position, view_pos) * lights.data[i].inv_radius; + float d = distance(lights.data[i].position, view_pos); vec3 shadow_attenuation = vec3(1.0); - if (d < 1.0) { + if (d * lights.data[i].inv_radius < 1.0) { vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy); vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular); - float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x); + float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x); vec3 light = attenuation_energy.y * color_specular.rgb / M_PI; @@ -326,14 +335,14 @@ void main() { vec3 light_pos = lights.data[i].position; vec3 light_rel_vec = lights.data[i].position - view_pos; - float d = length(light_rel_vec) * lights.data[i].inv_radius; + float d = length(light_rel_vec); vec3 shadow_attenuation = vec3(1.0); - if (d < 1.0) { + if (d * lights.data[i].inv_radius < 1.0) { vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy); vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular); - float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x); + float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x); vec3 spot_dir = lights.data[i].direction; vec2 spot_att_angle = unpackHalf2x16(lights.data[i].cone_attenuation_angle); diff --git a/servers/rendering/renderer_scene.cpp b/servers/rendering/renderer_scene.cpp new file mode 100644 index 0000000000..dd544d4f3f --- /dev/null +++ b/servers/rendering/renderer_scene.cpp @@ -0,0 +1,37 @@ +/*************************************************************************/ +/* renderer_scene.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#include "renderer_scene.h" + +RendererScene::RendererScene() { +} + +RendererScene::~RendererScene() { +} diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h new file mode 100644 index 0000000000..c483898fed --- /dev/null +++ b/servers/rendering/renderer_scene.h @@ -0,0 +1,203 @@ +/*************************************************************************/ +/* renderer_scene.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RENDERINGSERVERSCENE_H +#define RENDERINGSERVERSCENE_H + +#include "servers/rendering/renderer_compositor.h" +#include "servers/xr/xr_interface.h" + +class RendererScene { +public: + virtual RID camera_create() = 0; + + virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0; + virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0; + virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0; + virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0; + virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0; + virtual void camera_set_environment(RID p_camera, RID p_env) = 0; + virtual void camera_set_camera_effects(RID p_camera, RID p_fx) = 0; + virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0; + virtual bool is_camera(RID p_camera) const = 0; + + virtual RID scenario_create() = 0; + + virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) = 0; + virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0; + virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx) = 0; + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0; + virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) = 0; + virtual bool is_scenario(RID p_scenario) const = 0; + virtual RID scenario_get_environment(RID p_scenario) = 0; + + virtual RID instance_create() = 0; + + virtual void instance_set_base(RID p_instance, RID p_base) = 0; + virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0; + virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0; + virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0; + virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; + virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; + virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0; + virtual void instance_set_visible(RID p_instance, bool p_visible) = 0; + + virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb) = 0; + + virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0; + virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0; + + virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0; + + // don't use these in a game! + virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0; + virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0; + virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0; + + virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) = 0; + virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) = 0; + virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0; + + virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0; + virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0; + virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0; + virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0; + + virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0; + virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; + virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0; + virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0; + + virtual void directional_shadow_atlas_set_size(int p_size) = 0; + + /* SKY API */ + + virtual RID sky_create() = 0; + virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; + virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0; + virtual void sky_set_material(RID p_sky, RID p_material) = 0; + virtual Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0; + + /* ENVIRONMENT API */ + + virtual RID environment_create() = 0; + + virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0; + virtual void environment_set_sky(RID p_env, RID p_sky) = 0; + virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; + virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; + virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; + virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; + virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; + + virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0; + virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; + virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; + + virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0; + + virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0; + virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0; + virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) = 0; + virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) = 0; + + virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0; + virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0; + + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0; + + 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) = 0; + + virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + + virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0; + virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0; + + virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; + + virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0; + + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; + + virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; + + virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0; + virtual int environment_get_canvas_max_layer(RID p_env) const = 0; + + virtual bool is_environment(RID p_environment) const = 0; + + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; + virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0; + virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0; + + /* Camera Effects */ + + virtual RID camera_effects_create() = 0; + + virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0; + virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0; + + virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; + virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; + + virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0; + virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0; + + virtual RID shadow_atlas_create() = 0; + virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0; + virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0; + + /* Render Buffers */ + + virtual RID render_buffers_create() = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0; + + virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; + + virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0; + virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0; + + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0; + + virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0; + virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas) = 0; + virtual void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_lod_threshold, RID p_shadow_atlas) = 0; + + virtual void update() = 0; + virtual void render_probes() = 0; + + virtual bool free(RID p_rid) = 0; + + RendererScene(); + virtual ~RendererScene(); +}; + +#endif // RENDERINGSERVERSCENE_H diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp new file mode 100644 index 0000000000..d3979521b1 --- /dev/null +++ b/servers/rendering/renderer_scene_cull.cpp @@ -0,0 +1,3508 @@ +/*************************************************************************/ +/* renderer_scene_cull.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#include "renderer_scene_cull.h" + +#include "core/config/project_settings.h" +#include "core/os/os.h" +#include "rendering_server_default.h" +#include "rendering_server_globals.h" + +#include <new> + +/* CAMERA API */ + +RID RendererSceneCull::camera_create() { + Camera *camera = memnew(Camera); + return camera_owner.make_rid(camera); +} + +void RendererSceneCull::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->type = Camera::PERSPECTIVE; + camera->fov = p_fovy_degrees; + camera->znear = p_z_near; + camera->zfar = p_z_far; +} + +void RendererSceneCull::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->type = Camera::ORTHOGONAL; + camera->size = p_size; + camera->znear = p_z_near; + camera->zfar = p_z_far; +} + +void RendererSceneCull::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->type = Camera::FRUSTUM; + camera->size = p_size; + camera->offset = p_offset; + camera->znear = p_z_near; + camera->zfar = p_z_far; +} + +void RendererSceneCull::camera_set_transform(RID p_camera, const Transform &p_transform) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->transform = p_transform.orthonormalized(); +} + +void RendererSceneCull::camera_set_cull_mask(RID p_camera, uint32_t p_layers) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + + camera->visible_layers = p_layers; +} + +void RendererSceneCull::camera_set_environment(RID p_camera, RID p_env) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->env = p_env; +} + +void RendererSceneCull::camera_set_camera_effects(RID p_camera, RID p_fx) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->effects = p_fx; +} + +void RendererSceneCull::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->vaspect = p_enable; +} + +bool RendererSceneCull::is_camera(RID p_camera) const { + return camera_owner.owns(p_camera); +} + +/* SCENARIO API */ + +void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) { + RendererSceneCull *self = (RendererSceneCull *)singleton; + Instance *A = p_A; + Instance *B = p_B; + + //instance indices are designed so greater always contains lesser + if (A->base_type > B->base_type) { + SWAP(A, B); //lesser always first + } + + if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + geom->lights.insert(B); + light->geometries.insert(A); + + if (geom->can_cast_shadows) { + light->shadow_dirty = true; + } + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY; + } + + } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + geom->reflection_probes.insert(B); + reflection_probe->geometries.insert(A); + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY; + } + + } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + geom->decals.insert(B); + decal->geometries.insert(A); + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_GEOM_DECAL_DIRTY; + } + + } else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + if (A->dynamic_gi) { + geom->lightmap_captures.insert(A); + lightmap_data->geometries.insert(B); + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_LIGHTMAP_CAPTURE; + } + ((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture + } + + } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + geom->gi_probes.insert(B); + + if (A->dynamic_gi) { + gi_probe->dynamic_geometries.insert(A); + } else { + gi_probe->geometries.insert(A); + } + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_GEOM_GI_PROBE_DIRTY; + } + + } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); + gi_probe->lights.insert(A); + } else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) { + InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data); + RSG::storage->particles_add_collision(A->base, collision->instance); + } +} + +void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) { + RendererSceneCull *self = (RendererSceneCull *)singleton; + Instance *A = p_A; + Instance *B = p_B; + + //instance indices are designed so greater always contains lesser + if (A->base_type > B->base_type) { + SWAP(A, B); //lesser always first + } + + if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + geom->lights.erase(B); + light->geometries.erase(A); + + if (geom->can_cast_shadows) { + light->shadow_dirty = true; + } + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY; + } + + } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + geom->reflection_probes.erase(B); + reflection_probe->geometries.erase(A); + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY; + } + + } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + geom->decals.erase(B); + decal->geometries.erase(A); + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_GEOM_DECAL_DIRTY; + } + + } else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + if (A->dynamic_gi) { + geom->lightmap_captures.erase(B); + + if (geom->lightmap_captures.is_empty() && A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags &= ~uint32_t(InstanceData::FLAG_LIGHTMAP_CAPTURE); + } + + lightmap_data->geometries.erase(A); + ((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture + } + + } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); + + geom->gi_probes.erase(B); + if (A->dynamic_gi) { + gi_probe->dynamic_geometries.erase(A); + } else { + gi_probe->geometries.erase(A); + } + + if (A->scenario && A->array_index >= 0) { + InstanceData &idata = A->scenario->instance_data[A->array_index]; + idata.flags |= InstanceData::FLAG_GEOM_GI_PROBE_DIRTY; + } + + } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); + gi_probe->lights.erase(A); + } else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) { + InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data); + RSG::storage->particles_remove_collision(A->base, collision->instance); + } +} + +RID RendererSceneCull::scenario_create() { + Scenario *scenario = memnew(Scenario); + ERR_FAIL_COND_V(!scenario, RID()); + RID scenario_rid = scenario_owner.make_rid(scenario); + scenario->self = scenario_rid; + + scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create(); + scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest + scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4); + scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4); + scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4); + scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8); + scenario->reflection_atlas = scene_render->reflection_atlas_create(); + + scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool); + scenario->instance_data.set_page_pool(&instance_data_page_pool); + + return scenario_rid; +} + +void RendererSceneCull::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->debug = p_debug_mode; +} + +void RendererSceneCull::scenario_set_environment(RID p_scenario, RID p_environment) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->environment = p_environment; +} + +void RendererSceneCull::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->camera_effects = p_camera_effects; +} + +void RendererSceneCull::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->fallback_environment = p_environment; +} + +void RendererSceneCull::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count); +} + +bool RendererSceneCull::is_scenario(RID p_scenario) const { + return scenario_owner.owns(p_scenario); +} + +RID RendererSceneCull::scenario_get_environment(RID p_scenario) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND_V(!scenario, RID()); + return scenario->environment; +} + +/* INSTANCING API */ + +void RendererSceneCull::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) { + if (p_update_aabb) { + p_instance->update_aabb = true; + } + if (p_update_dependencies) { + p_instance->update_dependencies = true; + } + + if (p_instance->update_item.in_list()) { + return; + } + + _instance_update_list.add(&p_instance->update_item); +} + +RID RendererSceneCull::instance_create() { + Instance *instance = memnew(Instance); + ERR_FAIL_COND_V(!instance, RID()); + + RID instance_rid = instance_owner.make_rid(instance); + instance->self = instance_rid; + + return instance_rid; +} + +void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) { + bool needs_instance = RSG::storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid()); + if (needs_instance != p_instance->mesh_instance.is_valid()) { + if (needs_instance) { + p_instance->mesh_instance = RSG::storage->mesh_instance_create(p_instance->base); + + } else { + RSG::storage->free(p_instance->mesh_instance); + p_instance->mesh_instance = RID(); + } + + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); + scene_render->geometry_instance_set_mesh_instance(geom->geometry_instance, p_instance->mesh_instance); + + if (p_instance->scenario && p_instance->array_index >= 0) { + InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index]; + if (p_instance->mesh_instance.is_valid()) { + idata.flags |= InstanceData::FLAG_USES_MESH_INSTANCE; + } else { + idata.flags &= ~uint32_t(InstanceData::FLAG_USES_MESH_INSTANCE); + } + } + } + + if (p_instance->mesh_instance.is_valid()) { + RSG::storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton); + } +} + +void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + Scenario *scenario = instance->scenario; + + if (instance->base_type != RS::INSTANCE_NONE) { + //free anything related to that base + + if (scenario && instance->indexer_id.is_valid()) { + _unpair_instance(instance); + } + + if (instance->mesh_instance.is_valid()) { + RSG::storage->free(instance->mesh_instance); + instance->mesh_instance = RID(); + // no need to set instance data flag here, as it was freed above + } + + switch (instance->base_type) { + case RS::INSTANCE_MESH: + case RS::INSTANCE_MULTIMESH: + case RS::INSTANCE_IMMEDIATE: + case RS::INSTANCE_PARTICLES: { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_free(geom->geometry_instance); + } break; + case RS::INSTANCE_LIGHT: { + InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); + + if (scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + scenario->dynamic_lights.erase(light->instance); + } + +#ifdef DEBUG_ENABLED + if (light->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from light."); + } +#endif + if (scenario && light->D) { + scenario->directional_lights.erase(light->D); + light->D = nullptr; + } + scene_render->free(light->instance); + } break; + case RS::INSTANCE_PARTICLES_COLLISION: { + InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data); + RSG::storage->free(collision->instance); + } break; + case RS::INSTANCE_REFLECTION_PROBE: { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data); + scene_render->free(reflection_probe->instance); + if (reflection_probe->update_list.in_list()) { + reflection_probe_render_list.remove(&reflection_probe->update_list); + } + } break; + case RS::INSTANCE_DECAL: { + InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data); + scene_render->free(decal->instance); + + } break; + case RS::INSTANCE_LIGHTMAP: { + InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(instance->base_data); + //erase dependencies, since no longer a lightmap + while (lightmap_data->users.front()) { + instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0); + } + scene_render->free(lightmap_data->instance); + } break; + case RS::INSTANCE_GI_PROBE: { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data); +#ifdef DEBUG_ENABLED + if (gi_probe->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); + } +#endif +#ifdef DEBUG_ENABLED + if (gi_probe->lights.size()) { + ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); + } +#endif + if (gi_probe->update_element.in_list()) { + gi_probe_update_list.remove(&gi_probe->update_element); + } + + scene_render->free(gi_probe->probe_instance); + + } break; + default: { + } + } + + if (instance->base_data) { + memdelete(instance->base_data); + instance->base_data = nullptr; + } + + instance->materials.clear(); + } + + instance->base_type = RS::INSTANCE_NONE; + instance->base = RID(); + + if (p_base.is_valid()) { + instance->base_type = RSG::storage->get_base_type(p_base); + ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE); + + switch (instance->base_type) { + case RS::INSTANCE_LIGHT: { + InstanceLightData *light = memnew(InstanceLightData); + + if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) { + light->D = scenario->directional_lights.push_back(instance); + } + + light->instance = scene_render->light_instance_create(p_base); + + instance->base_data = light; + } break; + case RS::INSTANCE_MESH: + case RS::INSTANCE_MULTIMESH: + case RS::INSTANCE_IMMEDIATE: + case RS::INSTANCE_PARTICLES: { + InstanceGeometryData *geom = memnew(InstanceGeometryData); + instance->base_data = geom; + geom->geometry_instance = scene_render->geometry_instance_create(p_base); + + scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton); + scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override); + scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials); + scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb); + scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask); + scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, instance->lod_bias); + scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, instance->baked_light); + scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi); + scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); + scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index); + if (instance->lightmap_sh.size() == 9) { + scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr()); + } + + } break; + case RS::INSTANCE_PARTICLES_COLLISION: { + InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData); + collision->instance = RSG::storage->particles_collision_instance_create(p_base); + RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible); + instance->base_data = collision; + } break; + case RS::INSTANCE_REFLECTION_PROBE: { + InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData); + reflection_probe->owner = instance; + instance->base_data = reflection_probe; + + reflection_probe->instance = scene_render->reflection_probe_instance_create(p_base); + } break; + case RS::INSTANCE_DECAL: { + InstanceDecalData *decal = memnew(InstanceDecalData); + decal->owner = instance; + instance->base_data = decal; + + decal->instance = scene_render->decal_instance_create(p_base); + } break; + case RS::INSTANCE_LIGHTMAP: { + InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData); + instance->base_data = lightmap_data; + lightmap_data->instance = scene_render->lightmap_instance_create(p_base); + } break; + case RS::INSTANCE_GI_PROBE: { + InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData); + instance->base_data = gi_probe; + gi_probe->owner = instance; + + if (scenario && !gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + + gi_probe->probe_instance = scene_render->gi_probe_instance_create(p_base); + + } break; + default: { + } + } + + instance->base = p_base; + + if (instance->base_type == RS::INSTANCE_MESH) { + _instance_update_mesh_instance(instance); + } + + //forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it + RSG::storage->base_update_dependency(p_base, &instance->dependency_tracker); + } + + _instance_queue_update(instance, true, true); +} + +void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->scenario) { + instance->scenario->instances.remove(&instance->scenario_item); + + if (instance->indexer_id.is_valid()) { + _unpair_instance(instance); + } + + switch (instance->base_type) { + case RS::INSTANCE_LIGHT: { + InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); +#ifdef DEBUG_ENABLED + if (light->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from light."); + } +#endif + if (light->D) { + instance->scenario->directional_lights.erase(light->D); + light->D = nullptr; + } + } break; + case RS::INSTANCE_REFLECTION_PROBE: { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data); + scene_render->reflection_probe_release_atlas_index(reflection_probe->instance); + + } break; + case RS::INSTANCE_PARTICLES_COLLISION: { + heightfield_particle_colliders_update_list.erase(instance); + } break; + case RS::INSTANCE_GI_PROBE: { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data); + +#ifdef DEBUG_ENABLED + if (gi_probe->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); + } +#endif +#ifdef DEBUG_ENABLED + if (gi_probe->lights.size()) { + ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); + } +#endif + + if (gi_probe->update_element.in_list()) { + gi_probe_update_list.remove(&gi_probe->update_element); + } + } break; + default: { + } + } + + instance->scenario = nullptr; + } + + if (p_scenario.is_valid()) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + + instance->scenario = scenario; + + scenario->instances.add(&instance->scenario_item); + + switch (instance->base_type) { + case RS::INSTANCE_LIGHT: { + InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); + + if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) { + light->D = scenario->directional_lights.push_back(instance); + } + } break; + case RS::INSTANCE_GI_PROBE: { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data); + if (!gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + } break; + default: { + } + } + + _instance_queue_update(instance, true, true); + } +} + +void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->layer_mask = p_mask; + if (instance->scenario && instance->array_index >= 0) { + instance->scenario->instance_data[instance->array_index].layer_mask = p_mask; + } + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, p_mask); + } +} + +void RendererSceneCull::instance_set_transform(RID p_instance, const Transform &p_transform) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->transform == p_transform) { + return; //must be checked to avoid worst evil + } + +#ifdef DEBUG_ENABLED + + for (int i = 0; i < 4; i++) { + const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin; + ERR_FAIL_COND(Math::is_inf(v.x)); + ERR_FAIL_COND(Math::is_nan(v.x)); + ERR_FAIL_COND(Math::is_inf(v.y)); + ERR_FAIL_COND(Math::is_nan(v.y)); + ERR_FAIL_COND(Math::is_inf(v.z)); + ERR_FAIL_COND(Math::is_nan(v.z)); + } + +#endif + instance->transform = p_transform; + _instance_queue_update(instance, true); +} + +void RendererSceneCull::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->object_id = p_id; +} + +void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } + + if (instance->mesh_instance.is_valid()) { + RSG::storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight); + } +} + +void RendererSceneCull::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->base_type == RS::INSTANCE_MESH) { + //may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case + instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base))); + } + + ERR_FAIL_INDEX(p_surface, instance->materials.size()); + + instance->materials.write[p_surface] = p_material; + + _instance_queue_update(instance, false, true); +} + +void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->visible == p_visible) { + return; + } + + instance->visible = p_visible; + + if (p_visible) { + if (instance->scenario != nullptr) { + _instance_queue_update(instance, true, false); + } + } else if (instance->indexer_id.is_valid()) { + _unpair_instance(instance); + } + + if (instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { + InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data); + RSG::storage->particles_collision_instance_set_active(collision->instance, p_visible); + } +} + +inline bool is_geometry_instance(RenderingServer::InstanceType p_type) { + return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE; +} + +void RendererSceneCull::instance_set_custom_aabb(RID p_instance, AABB p_aabb) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + ERR_FAIL_COND(!is_geometry_instance(instance->base_type)); + + if (p_aabb != AABB()) { + // Set custom AABB + if (instance->custom_aabb == nullptr) { + instance->custom_aabb = memnew(AABB); + } + *instance->custom_aabb = p_aabb; + + } else { + // Clear custom AABB + if (instance->custom_aabb != nullptr) { + memdelete(instance->custom_aabb); + instance->custom_aabb = nullptr; + } + } + + if (instance->scenario) { + _instance_queue_update(instance, true, false); + } +} + +void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->skeleton == p_skeleton) { + return; + } + + instance->skeleton = p_skeleton; + + if (p_skeleton.is_valid()) { + //update the dependency now, so if cleared, we remove it + RSG::storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker); + } + + _instance_queue_update(instance, true, true); + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + _instance_update_mesh_instance(instance); + + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_skeleton(geom->geometry_instance, p_skeleton); + } +} + +void RendererSceneCull::instance_set_exterior(RID p_instance, bool p_enabled) { +} + +void RendererSceneCull::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->extra_margin = p_margin; + _instance_queue_update(instance, true, false); +} + +Vector<ObjectID> RendererSceneCull::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const { + Vector<ObjectID> instances; + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND_V(!scenario, instances); + + const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling + + struct CullAABB { + Vector<ObjectID> instances; + _FORCE_INLINE_ bool operator()(void *p_data) { + Instance *p_instance = (Instance *)p_data; + if (!p_instance->object_id.is_null()) { + instances.push_back(p_instance->object_id); + } + return false; + } + }; + + CullAABB cull_aabb; + scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(p_aabb, cull_aabb); + scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(p_aabb, cull_aabb); + return cull_aabb.instances; +} + +Vector<ObjectID> RendererSceneCull::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { + Vector<ObjectID> instances; + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND_V(!scenario, instances); + const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling + + struct CullRay { + Vector<ObjectID> instances; + _FORCE_INLINE_ bool operator()(void *p_data) { + Instance *p_instance = (Instance *)p_data; + if (!p_instance->object_id.is_null()) { + instances.push_back(p_instance->object_id); + } + return false; + } + }; + + CullRay cull_ray; + scenario->indexers[Scenario::INDEXER_GEOMETRY].ray_query(p_from, p_to, cull_ray); + scenario->indexers[Scenario::INDEXER_VOLUMES].ray_query(p_from, p_to, cull_ray); + return cull_ray.instances; +} + +Vector<ObjectID> RendererSceneCull::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const { + Vector<ObjectID> instances; + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND_V(!scenario, instances); + const_cast<RendererSceneCull *>(this)->update_dirty_instances(); // check dirty instances before culling + + Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&p_convex[0], p_convex.size()); + + struct CullConvex { + Vector<ObjectID> instances; + _FORCE_INLINE_ bool operator()(void *p_data) { + Instance *p_instance = (Instance *)p_data; + if (!p_instance->object_id.is_null()) { + instances.push_back(p_instance->object_id); + } + return false; + } + }; + + CullConvex cull_convex; + scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(p_convex.ptr(), p_convex.size(), points.ptr(), points.size(), cull_convex); + scenario->indexers[Scenario::INDEXER_VOLUMES].convex_query(p_convex.ptr(), p_convex.size(), points.ptr(), points.size(), cull_convex); + return cull_convex.instances; +} + +void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + //ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK)); + + switch (p_flags) { + case RS::INSTANCE_FLAG_USE_BAKED_LIGHT: { + instance->baked_light = p_enabled; + + if (instance->scenario && instance->array_index >= 0) { + InstanceData &idata = instance->scenario->instance_data[instance->array_index]; + if (instance->baked_light) { + idata.flags |= InstanceData::FLAG_USES_BAKED_LIGHT; + } else { + idata.flags &= ~uint32_t(InstanceData::FLAG_USES_BAKED_LIGHT); + } + } + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, p_enabled); + } + + } break; + case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: { + if (p_enabled == instance->dynamic_gi) { + //bye, redundant + return; + } + + if (instance->indexer_id.is_valid()) { + _unpair_instance(instance); + _instance_queue_update(instance, true, true); + } + + //once out of octree, can be changed + instance->dynamic_gi = p_enabled; + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, p_enabled); + } + + } break; + case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: { + instance->redraw_if_visible = p_enabled; + + if (instance->scenario && instance->array_index >= 0) { + InstanceData &idata = instance->scenario->instance_data[instance->array_index]; + if (instance->redraw_if_visible) { + idata.flags |= InstanceData::FLAG_REDRAW_IF_VISIBLE; + } else { + idata.flags &= ~uint32_t(InstanceData::FLAG_REDRAW_IF_VISIBLE); + } + } + + } break; + default: { + } + } +} + +void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->cast_shadows = p_shadow_casting_setting; + + if (instance->scenario && instance->array_index >= 0) { + InstanceData &idata = instance->scenario->instance_data[instance->array_index]; + + if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + idata.flags |= InstanceData::FLAG_CAST_SHADOWS; + } else { + idata.flags &= ~uint32_t(InstanceData::FLAG_CAST_SHADOWS); + } + + if (instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + idata.flags |= InstanceData::FLAG_CAST_SHADOWS_ONLY; + } else { + idata.flags &= ~uint32_t(InstanceData::FLAG_CAST_SHADOWS_ONLY); + } + } + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED); + } + + _instance_queue_update(instance, false, true); +} + +void RendererSceneCull::instance_geometry_set_material_override(RID p_instance, RID p_material) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->material_override = p_material; + _instance_queue_update(instance, false, true); + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_material_override(geom->geometry_instance, p_material); + } +} + +void RendererSceneCull::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) { +} + +void RendererSceneCull::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) { +} + +void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->lightmap) { + InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(((Instance *)instance->lightmap)->base_data); + lightmap_data->users.erase(instance); + instance->lightmap = nullptr; + } + + Instance *lightmap_instance = instance_owner.getornull(p_lightmap); + + instance->lightmap = lightmap_instance; + instance->lightmap_uv_scale = p_lightmap_uv_scale; + instance->lightmap_slice_index = p_slice_index; + + RID lightmap_instance_rid; + + if (lightmap_instance) { + InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data); + lightmap_data->users.insert(instance); + lightmap_instance_rid = lightmap_data->instance; + } + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index); + } +} + +void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->lod_bias = p_lod_bias; + + if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, p_lod_bias); + } +} + +void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter); + + if (!E) { + Instance::InstanceShaderParameter isp; + isp.index = -1; + isp.info = PropertyInfo(); + isp.value = p_value; + instance->instance_shader_parameters[p_parameter] = isp; + } else { + E->get().value = p_value; + if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) { + //update directly + RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value); + } + } +} + +Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const { + const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!instance, Variant()); + + if (instance->instance_shader_parameters.has(p_parameter)) { + return instance->instance_shader_parameters[p_parameter].value; + } + return Variant(); +} + +Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const { + const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!instance, Variant()); + + if (instance->instance_shader_parameters.has(p_parameter)) { + return instance->instance_shader_parameters[p_parameter].default_value; + } + return Variant(); +} + +void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const { + const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + const_cast<RendererSceneCull *>(this)->update_dirty_instances(); + + Vector<StringName> names; + for (Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) { + names.push_back(E->key()); + } + names.sort_custom<StringName::AlphCompare>(); + for (int i = 0; i < names.size(); i++) { + PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info; + p_parameters->push_back(pinfo); + } +} + +void RendererSceneCull::_update_instance(Instance *p_instance) { + p_instance->version++; + + if (p_instance->base_type == RS::INSTANCE_LIGHT) { + InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); + + scene_render->light_instance_set_transform(light->instance, p_instance->transform); + scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb)); + light->shadow_dirty = true; + + RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base); + if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) { + if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + p_instance->scenario->dynamic_lights.erase(light->instance); + } + + light->bake_mode = bake_mode; + + if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + p_instance->scenario->dynamic_lights.push_back(light->instance); + } + } + + uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base); + if (light->max_sdfgi_cascade != max_sdfgi_cascade) { + light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario + } + } else if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data); + + scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform); + + if (p_instance->scenario && p_instance->array_index >= 0) { + InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index]; + idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY; + } + } else if (p_instance->base_type == RS::INSTANCE_DECAL) { + InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data); + + scene_render->decal_instance_set_transform(decal->instance, p_instance->transform); + } else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) { + InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data); + + scene_render->lightmap_instance_set_transform(lightmap->instance, p_instance->transform); + } else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data); + + scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform); + } else if (p_instance->base_type == RS::INSTANCE_PARTICLES) { + RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform); + } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { + InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(p_instance->base_data); + + //remove materials no longer used and un-own them + if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) { + heightfield_particle_colliders_update_list.insert(p_instance); + } + RSG::storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform); + } + + if (p_instance->aabb.has_no_surface()) { + return; + } + + if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) { + //if this moved, update the captured objects + InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data); + //erase dependencies, since no longer a lightmap + + for (Set<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) { + Instance *geom = E->get(); + _instance_queue_update(geom, true, false); + } + } + + AABB new_aabb; + new_aabb = p_instance->transform.xform(p_instance->aabb); + p_instance->transformed_aabb = new_aabb; + + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); + //make sure lights are updated if it casts shadow + + if (geom->can_cast_shadows) { + for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); + light->shadow_dirty = true; + } + } + + if (!p_instance->lightmap && geom->lightmap_captures.size()) { + //affected by lightmap captures, must update capture info! + _update_instance_lightmap_captures(p_instance); + } else { + if (!p_instance->lightmap_sh.is_empty()) { + p_instance->lightmap_sh.clear(); //don't need SH + p_instance->lightmap_target_sh.clear(); //don't need SH + scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, nullptr); + } + } + + scene_render->geometry_instance_set_transform(geom->geometry_instance, p_instance->transform, p_instance->aabb, p_instance->transformed_aabb); + } + + if (p_instance->scenario == nullptr || !p_instance->visible || Math::is_zero_approx(p_instance->transform.basis.determinant())) { + p_instance->prev_transformed_aabb = p_instance->transformed_aabb; + return; + } + + //quantize to improve moving object performance + AABB bvh_aabb = p_instance->transformed_aabb; + + if (p_instance->indexer_id.is_valid() && bvh_aabb != p_instance->prev_transformed_aabb) { + //assume motion, see if bounds need to be quantized + AABB motion_aabb = bvh_aabb.merge(p_instance->prev_transformed_aabb); + float motion_longest_axis = motion_aabb.get_longest_axis_size(); + float longest_axis = p_instance->transformed_aabb.get_longest_axis_size(); + + if (motion_longest_axis < longest_axis * 2) { + //moved but not a lot, use motion aabb quantizing + float quantize_size = Math::pow(2.0, Math::ceil(Math::log(motion_longest_axis) / Math::log(2.0))) * 0.5; //one fifth + bvh_aabb.quantize(quantize_size); + } + } + + if (!p_instance->indexer_id.is_valid()) { + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].insert(bvh_aabb, p_instance); + } else { + p_instance->indexer_id = p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].insert(bvh_aabb, p_instance); + } + + p_instance->array_index = p_instance->scenario->instance_data.size(); + InstanceData idata; + idata.instance = p_instance; + idata.layer_mask = p_instance->layer_mask; + idata.flags = p_instance->base_type; //changing it means de-indexing, so this never needs to be changed later + idata.base_rid = p_instance->base; + switch (p_instance->base_type) { + case RS::INSTANCE_MESH: + case RS::INSTANCE_MULTIMESH: + case RS::INSTANCE_IMMEDIATE: + case RS::INSTANCE_PARTICLES: { + idata.instance_geometry = static_cast<InstanceGeometryData *>(p_instance->base_data)->geometry_instance; + } break; + case RS::INSTANCE_LIGHT: { + idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance.get_id(); + } break; + case RS::INSTANCE_REFLECTION_PROBE: { + idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance.get_id(); + } break; + case RS::INSTANCE_DECAL: { + idata.instance_data_rid = static_cast<InstanceDecalData *>(p_instance->base_data)->instance.get_id(); + } break; + case RS::INSTANCE_LIGHTMAP: { + idata.instance_data_rid = static_cast<InstanceLightmapData *>(p_instance->base_data)->instance.get_id(); + } break; + case RS::INSTANCE_GI_PROBE: { + idata.instance_data_rid = static_cast<InstanceGIProbeData *>(p_instance->base_data)->probe_instance.get_id(); + } break; + default: { + } + } + + if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) { + //always dirty when added + idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY; + } + if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + idata.flags |= InstanceData::FLAG_CAST_SHADOWS; + } + if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + idata.flags |= InstanceData::FLAG_CAST_SHADOWS_ONLY; + } + if (p_instance->redraw_if_visible) { + idata.flags |= InstanceData::FLAG_REDRAW_IF_VISIBLE; + } + // dirty flags should not be set here, since no pairing has happened + if (p_instance->baked_light) { + idata.flags |= InstanceData::FLAG_USES_BAKED_LIGHT; + } + if (p_instance->mesh_instance.is_valid()) { + idata.flags |= InstanceData::FLAG_USES_MESH_INSTANCE; + } + + p_instance->scenario->instance_data.push_back(idata); + p_instance->scenario->instance_aabbs.push_back(InstanceBounds(p_instance->transformed_aabb)); + } else { + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].update(p_instance->indexer_id, bvh_aabb); + } else { + p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].update(p_instance->indexer_id, bvh_aabb); + } + p_instance->scenario->instance_aabbs[p_instance->array_index] = InstanceBounds(p_instance->transformed_aabb); + } + + //move instance and repair + pair_pass++; + + PairInstances pair; + + pair.instance = p_instance; + pair.pair_allocator = &pair_allocator; + pair.pair_pass = pair_pass; + pair.pair_mask = 0; + + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + pair.pair_mask |= 1 << RS::INSTANCE_LIGHT; + pair.pair_mask |= 1 << RS::INSTANCE_GI_PROBE; + pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP; + + pair.pair_mask |= geometry_instance_pair_mask; + + pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES]; + } else if (p_instance->base_type == RS::INSTANCE_LIGHT) { + pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK; + pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; + + if (RSG::storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) { + pair.pair_mask |= (1 << RS::INSTANCE_GI_PROBE); + pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES]; + } + } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) { + pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; + pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; + } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (p_instance->base_type == RS::INSTANCE_DECAL)) { + pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; + pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; + } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { + pair.pair_mask = (1 << RS::INSTANCE_PARTICLES); + pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; + } else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) { + //lights and geometries + pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT); + pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; + pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES]; + } + + pair.pair(); + + p_instance->prev_transformed_aabb = p_instance->transformed_aabb; +} + +void RendererSceneCull::_unpair_instance(Instance *p_instance) { + if (!p_instance->indexer_id.is_valid()) { + return; //nothing to do + } + + while (p_instance->pairs.first()) { + InstancePair *pair = p_instance->pairs.first()->self(); + Instance *other_instance = p_instance == pair->a ? pair->b : pair->a; + _instance_unpair(p_instance, other_instance); + pair_allocator.free(pair); + } + + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY].remove(p_instance->indexer_id); + } else { + p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES].remove(p_instance->indexer_id); + } + + p_instance->indexer_id = DynamicBVH::ID(); + + //replace this by last + int32_t swap_with_index = p_instance->scenario->instance_data.size() - 1; + if (swap_with_index != p_instance->array_index) { + p_instance->scenario->instance_data[swap_with_index].instance->array_index = p_instance->array_index; //swap + p_instance->scenario->instance_data[p_instance->array_index] = p_instance->scenario->instance_data[swap_with_index]; + p_instance->scenario->instance_aabbs[p_instance->array_index] = p_instance->scenario->instance_aabbs[swap_with_index]; + } + + // pop last + p_instance->scenario->instance_data.pop_back(); + p_instance->scenario->instance_aabbs.pop_back(); + + //uninitialize + p_instance->array_index = -1; + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + // Clear these now because the InstanceData containing the dirty flags is gone + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); + + scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0); + scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0); + scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0); + scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, nullptr, 0); + } +} + +void RendererSceneCull::_update_instance_aabb(Instance *p_instance) { + AABB new_aabb; + + ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_NONE && !p_instance->base.is_valid()); + + switch (p_instance->base_type) { + case RenderingServer::INSTANCE_NONE: { + // do nothing + } break; + case RenderingServer::INSTANCE_MESH: { + if (p_instance->custom_aabb) { + new_aabb = *p_instance->custom_aabb; + } else { + new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton); + } + + } break; + + case RenderingServer::INSTANCE_MULTIMESH: { + if (p_instance->custom_aabb) { + new_aabb = *p_instance->custom_aabb; + } else { + new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base); + } + + } break; + case RenderingServer::INSTANCE_IMMEDIATE: { + if (p_instance->custom_aabb) { + new_aabb = *p_instance->custom_aabb; + } else { + new_aabb = RSG::storage->immediate_get_aabb(p_instance->base); + } + + } break; + case RenderingServer::INSTANCE_PARTICLES: { + if (p_instance->custom_aabb) { + new_aabb = *p_instance->custom_aabb; + } else { + new_aabb = RSG::storage->particles_get_aabb(p_instance->base); + } + + } break; + case RenderingServer::INSTANCE_PARTICLES_COLLISION: { + new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_LIGHT: { + new_aabb = RSG::storage->light_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_REFLECTION_PROBE: { + new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_DECAL: { + new_aabb = RSG::storage->decal_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_GI_PROBE: { + new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base); + + } break; + case RenderingServer::INSTANCE_LIGHTMAP: { + new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base); + + } break; + default: { + } + } + + // <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs + if (p_instance->extra_margin) { + new_aabb.grow_by(p_instance->extra_margin); + } + + p_instance->aabb = new_aabb; +} + +void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance) { + bool first_set = p_instance->lightmap_sh.size() == 0; + p_instance->lightmap_sh.resize(9); //using SH + p_instance->lightmap_target_sh.resize(9); //using SH + Color *instance_sh = p_instance->lightmap_target_sh.ptrw(); + bool inside = false; + Color accum_sh[9]; + float accum_blend = 0.0; + + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); + for (Set<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { + Instance *lightmap = E->get(); + + bool interior = RSG::storage->lightmap_is_interior(lightmap->base); + + if (inside && !interior) { + continue; //we are inside, ignore exteriors + } + + Transform to_bounds = lightmap->transform.affine_inverse(); + Vector3 center = p_instance->transform.xform(p_instance->aabb.position + p_instance->aabb.size * 0.5); //use aabb center + + Vector3 lm_pos = to_bounds.xform(center); + + AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base); + if (!bounds.has_point(lm_pos)) { + continue; //not in this lightmap + } + + Color sh[9]; + RSG::storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh); + + //rotate it + Basis rot = lightmap->transform.basis.orthonormalized(); + for (int i = 0; i < 3; i++) { + float csh[9]; + for (int j = 0; j < 9; j++) { + csh[j] = sh[j][i]; + } + rot.rotate_sh(csh); + for (int j = 0; j < 9; j++) { + sh[j][i] = csh[j]; + } + } + + Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0); + + float blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z)); + //make blend more rounded + blend = Math::lerp(inner_pos.length(), blend, blend); + blend *= blend; + blend = MAX(0.0, 1.0 - blend); + + if (interior && !inside) { + //do not blend, just replace + for (int j = 0; j < 9; j++) { + accum_sh[j] = sh[j] * blend; + } + accum_blend = blend; + inside = true; + } else { + for (int j = 0; j < 9; j++) { + accum_sh[j] += sh[j] * blend; + } + accum_blend += blend; + } + } + + if (accum_blend > 0.0) { + for (int j = 0; j < 9; j++) { + instance_sh[j] = accum_sh[j] / accum_blend; + if (first_set) { + p_instance->lightmap_sh.write[j] = instance_sh[j]; + } + } + } + + scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, p_instance->lightmap_sh.ptr()); +} + +void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) { + InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); + + Transform light_transform = p_instance->transform; + light_transform.orthonormalize(); //scale does not count on lights + + real_t max_distance = p_cam_projection.get_z_far(); + real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE); + if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera + max_distance = MIN(shadow_max, max_distance); + } + max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001); + real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance); + + RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base); + + real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE); + + real_t range = max_distance - min_distance; + + int splits = 0; + switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) { + case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: + splits = 1; + break; + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + splits = 2; + break; + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: + splits = 4; + break; + } + + real_t distances[5]; + + distances[0] = min_distance; + for (int i = 0; i < splits; i++) { + distances[i + 1] = min_distance + RSG::storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range; + }; + + distances[splits] = max_distance; + + real_t texture_size = scene_render->get_directional_light_shadow_size(light->instance); + + bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base); + + real_t first_radius = 0.0; + + real_t min_distance_bias_scale = distances[1]; + + cull.shadow_count = p_shadow_index + 1; + cull.shadows[p_shadow_index].cascade_count = splits; + cull.shadows[p_shadow_index].light_instance = light->instance; + + for (int i = 0; i < splits; i++) { + RENDER_TIMESTAMP("Culling Directional Light split" + itos(i)); + + // setup a camera matrix for that range! + CameraMatrix camera_matrix; + + real_t aspect = p_cam_projection.get_aspect(); + + if (p_cam_orthogonal) { + Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); + + camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); + } else { + real_t fov = p_cam_projection.get_fov(); //this is actually yfov, because set aspect tries to keep it + camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true); + } + + //obtain the frustum endpoints + + Vector3 endpoints[8]; // frustum plane endpoints + bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints); + ERR_CONTINUE(!res); + + // obtain the light frustum ranges (given endpoints) + + Transform transform = light_transform; //discard scale and stabilize light + + Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized(); + Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized(); + Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized(); + //z_vec points against the camera, like in default opengl + + real_t x_min = 0.f, x_max = 0.f; + real_t y_min = 0.f, y_max = 0.f; + real_t z_min = 0.f, z_max = 0.f; + + // FIXME: z_max_cam is defined, computed, but not used below when setting up + // ortho_camera. Commented out for now to fix warnings but should be investigated. + real_t x_min_cam = 0.f, x_max_cam = 0.f; + real_t y_min_cam = 0.f, y_max_cam = 0.f; + real_t z_min_cam = 0.f; + //real_t z_max_cam = 0.f; + + real_t bias_scale = 1.0; + real_t aspect_bias_scale = 1.0; + + //used for culling + + for (int j = 0; j < 8; j++) { + real_t d_x = x_vec.dot(endpoints[j]); + real_t d_y = y_vec.dot(endpoints[j]); + real_t d_z = z_vec.dot(endpoints[j]); + + if (j == 0 || d_x < x_min) { + x_min = d_x; + } + if (j == 0 || d_x > x_max) { + x_max = d_x; + } + + if (j == 0 || d_y < y_min) { + y_min = d_y; + } + if (j == 0 || d_y > y_max) { + y_max = d_y; + } + + if (j == 0 || d_z < z_min) { + z_min = d_z; + } + if (j == 0 || d_z > z_max) { + z_max = d_z; + } + } + + real_t radius = 0; + real_t soft_shadow_expand = 0; + Vector3 center; + + { + //camera viewport stuff + + for (int j = 0; j < 8; j++) { + center += endpoints[j]; + } + center /= 8.0; + + //center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5; + + for (int j = 0; j < 8; j++) { + real_t d = center.distance_to(endpoints[j]); + if (d > radius) { + radius = d; + } + } + + radius *= texture_size / (texture_size - 2.0); //add a texel by each side + + if (i == 0) { + first_radius = radius; + } else { + bias_scale = radius / first_radius; + } + + z_min_cam = z_vec.dot(center) - radius; + + { + float soft_shadow_angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE); + + if (soft_shadow_angle > 0.0) { + float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam; + soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range; + + x_max += soft_shadow_expand; + y_max += soft_shadow_expand; + + x_min -= soft_shadow_expand; + y_min -= soft_shadow_expand; + } + } + + x_max_cam = x_vec.dot(center) + radius + soft_shadow_expand; + x_min_cam = x_vec.dot(center) - radius - soft_shadow_expand; + y_max_cam = y_vec.dot(center) + radius + soft_shadow_expand; + y_min_cam = y_vec.dot(center) - radius - soft_shadow_expand; + + if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) { + //this trick here is what stabilizes the shadow (make potential jaggies to not move) + //at the cost of some wasted resolution. Still the quality increase is very well worth it + + real_t unit = radius * 2.0 / texture_size; + + x_max_cam = Math::snapped(x_max_cam, unit); + x_min_cam = Math::snapped(x_min_cam, unit); + y_max_cam = Math::snapped(y_max_cam, unit); + y_min_cam = Math::snapped(y_min_cam, unit); + } + } + + //now that we know all ranges, we can proceed to make the light frustum planes, for culling octree + + Vector<Plane> light_frustum_planes; + light_frustum_planes.resize(6); + + //right/left + light_frustum_planes.write[0] = Plane(x_vec, x_max); + light_frustum_planes.write[1] = Plane(-x_vec, -x_min); + //top/bottom + light_frustum_planes.write[2] = Plane(y_vec, y_max); + light_frustum_planes.write[3] = Plane(-y_vec, -y_min); + //near/far + light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6); + light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed + + // a pre pass will need to be needed to determine the actual z-near to be used + + if (pancake_size > 0) { + z_max = z_vec.dot(center) + radius + pancake_size; + } + + if (aspect != 1.0) { + // if the aspect is different, then the radius will become larger. + // if this happens, then bias needs to be adjusted too, as depth will increase + // to do this, compare the depth of one that would have resulted from a square frustum + + CameraMatrix camera_matrix_square; + if (p_cam_orthogonal) { + Vector2 vp_he = camera_matrix.get_viewport_half_extents(); + if (p_cam_vaspect) { + camera_matrix_square.set_orthogonal(vp_he.x * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true); + } else { + camera_matrix_square.set_orthogonal(vp_he.y * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); + } + } else { + Vector2 vp_he = camera_matrix.get_viewport_half_extents(); + if (p_cam_vaspect) { + camera_matrix_square.set_frustum(vp_he.x * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true); + } else { + camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); + } + } + + Vector3 endpoints_square[8]; // frustum plane endpoints + res = camera_matrix_square.get_endpoints(p_cam_transform, endpoints_square); + ERR_CONTINUE(!res); + Vector3 center_square; + + for (int j = 0; j < 8; j++) { + center_square += endpoints_square[j]; + } + + center_square /= 8.0; + + real_t radius_square = 0; + + for (int j = 0; j < 8; j++) { + real_t d = center_square.distance_to(endpoints_square[j]); + if (d > radius_square) { + radius_square = d; + } + } + + radius_square *= texture_size / (texture_size - 2.0); //add a texel by each side + + float z_max_square = z_vec.dot(center_square) + radius_square + pancake_size; + + real_t z_min_cam_square = z_vec.dot(center_square) - radius_square; + + aspect_bias_scale = (z_max - z_min_cam) / (z_max_square - z_min_cam_square); + + // this is not entirely perfect, because the cull-adjusted z-max may be different + // but at least it's warranted that it results in a greater bias, so no acne should be present either way. + // pancaking also helps with this. + } + + { + CameraMatrix ortho_camera; + real_t half_x = (x_max_cam - x_min_cam) * 0.5; + real_t half_y = (y_max_cam - y_min_cam) * 0.5; + + ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam)); + + Vector2 uv_scale(1.0 / (x_max_cam - x_min_cam), 1.0 / (y_max_cam - y_min_cam)); + + Transform ortho_transform; + ortho_transform.basis = transform.basis; + ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max; + + cull.shadows[p_shadow_index].cascades[i].frustum = Frustum(light_frustum_planes); + cull.shadows[p_shadow_index].cascades[i].projection = ortho_camera; + cull.shadows[p_shadow_index].cascades[i].transform = ortho_transform; + cull.shadows[p_shadow_index].cascades[i].zfar = z_max - z_min_cam; + cull.shadows[p_shadow_index].cascades[i].split = distances[i + 1]; + cull.shadows[p_shadow_index].cascades[i].shadow_texel_size = radius * 2.0 / texture_size; + cull.shadows[p_shadow_index].cascades[i].bias_scale = bias_scale * aspect_bias_scale * min_distance_bias_scale; + cull.shadows[p_shadow_index].cascades[i].range_begin = z_max; + cull.shadows[p_shadow_index].cascades[i].uv_scale = uv_scale; + } + } +} + +bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_lod_threshold) { + InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); + + Transform light_transform = p_instance->transform; + light_transform.orthonormalize(); //scale does not count on lights + + bool animated_material_found = false; + + switch (RSG::storage->light_get_type(p_instance->base)) { + case RS::LIGHT_DIRECTIONAL: { + } break; + case RS::LIGHT_OMNI: { + RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base); + + if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !scene_render->light_instances_can_render_shadow_cube()) { + for (int i = 0; i < 2; i++) { + //using this one ensures that raster deferred will have it + RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i)); + + real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); + + real_t z = i == 0 ? -1 : 1; + Vector<Plane> planes; + planes.resize(6); + planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius)); + planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius)); + planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius)); + planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius)); + planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius)); + planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0)); + + geometry_instances_to_shadow_render.clear(); + instance_shadow_cull_result.clear(); + + Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size()); + + struct CullConvex { + PagedArray<Instance *> *result; + _FORCE_INLINE_ bool operator()(void *p_data) { + Instance *p_instance = (Instance *)p_data; + result->push_back(p_instance); + return false; + } + }; + + CullConvex cull_convex; + cull_convex.result = &instance_shadow_cull_result; + + p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex); + + Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z); + + for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { + continue; + } else { + if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { + animated_material_found = true; + } + + if (instance->mesh_instance.is_valid()) { + RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + } + } + + geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); + } + + RSG::storage->update_mesh_instances(); + + scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0); + scene_render->render_shadow(light->instance, p_shadow_atlas, i, geometry_instances_to_shadow_render); + } + } else { //shadow cube + + real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); + CameraMatrix cm; + cm.set_perspective(90, 1, 0.01, radius); + + for (int i = 0; i < 6; i++) { + RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i)); + //using this one ensures that raster deferred will have it + + static const Vector3 view_normals[6] = { + Vector3(+1, 0, 0), + Vector3(-1, 0, 0), + Vector3(0, -1, 0), + Vector3(0, +1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1) + }; + static const Vector3 view_up[6] = { + Vector3(0, -1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, -1), + Vector3(0, 0, +1), + Vector3(0, -1, 0), + Vector3(0, -1, 0) + }; + + Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]); + + Vector<Plane> planes = cm.get_projection_planes(xform); + + geometry_instances_to_shadow_render.clear(); + instance_shadow_cull_result.clear(); + + Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size()); + + struct CullConvex { + PagedArray<Instance *> *result; + _FORCE_INLINE_ bool operator()(void *p_data) { + Instance *p_instance = (Instance *)p_data; + result->push_back(p_instance); + return false; + } + }; + + CullConvex cull_convex; + cull_convex.result = &instance_shadow_cull_result; + + p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex); + + Plane near_plane(xform.origin, -xform.basis.get_axis(2)); + + for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { + continue; + } else { + if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { + animated_material_found = true; + } + if (instance->mesh_instance.is_valid()) { + RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + } + } + + geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); + } + + RSG::storage->update_mesh_instances(); + scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0); + scene_render->render_shadow(light->instance, p_shadow_atlas, i, geometry_instances_to_shadow_render); + } + + //restore the regular DP matrix + scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0); + } + + } break; + case RS::LIGHT_SPOT: { + RENDER_TIMESTAMP("Culling Spot Light"); + + real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); + real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); + + CameraMatrix cm; + cm.set_perspective(angle * 2.0, 1.0, 0.01, radius); + + Vector<Plane> planes = cm.get_projection_planes(light_transform); + + geometry_instances_to_shadow_render.clear(); + instance_shadow_cull_result.clear(); + + Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&planes[0], planes.size()); + + struct CullConvex { + PagedArray<Instance *> *result; + _FORCE_INLINE_ bool operator()(void *p_data) { + Instance *p_instance = (Instance *)p_data; + result->push_back(p_instance); + return false; + } + }; + + CullConvex cull_convex; + cull_convex.result = &instance_shadow_cull_result; + + p_scenario->indexers[Scenario::INDEXER_GEOMETRY].convex_query(planes.ptr(), planes.size(), points.ptr(), points.size(), cull_convex); + + Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); + + for (int j = 0; j < (int)instance_shadow_cull_result.size(); j++) { + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { + continue; + } else { + if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { + animated_material_found = true; + } + + if (instance->mesh_instance.is_valid()) { + RSG::storage->mesh_instance_check_for_update(instance->mesh_instance); + } + } + geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance); + } + + RSG::storage->update_mesh_instances(); + + scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0); + scene_render->render_shadow(light->instance, p_shadow_atlas, 0, geometry_instances_to_shadow_render); + + } break; + } + + return animated_material_found; +} + +void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) { +// render to mono camera +#ifndef _3D_DISABLED + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + + /* STEP 1 - SETUP CAMERA */ + CameraMatrix camera_matrix; + bool ortho = false; + + switch (camera->type) { + case Camera::ORTHOGONAL: { + camera_matrix.set_orthogonal( + camera->size, + p_viewport_size.width / (float)p_viewport_size.height, + camera->znear, + camera->zfar, + camera->vaspect); + ortho = true; + } break; + case Camera::PERSPECTIVE: { + camera_matrix.set_perspective( + camera->fov, + p_viewport_size.width / (float)p_viewport_size.height, + camera->znear, + camera->zfar, + camera->vaspect); + ortho = false; + + } break; + case Camera::FRUSTUM: { + camera_matrix.set_frustum( + camera->size, + p_viewport_size.width / (float)p_viewport_size.height, + camera->offset, + camera->znear, + camera->zfar, + camera->vaspect); + ortho = false; + } break; + } + + RID environment = _render_get_environment(p_camera, p_scenario); + + _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold); + _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold); +#endif +} + +void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas) { + // render for AR/VR interface + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + + /* SETUP CAMERA, we are ignoring type and FOV here */ + float aspect = p_viewport_size.width / (float)p_viewport_size.height; + CameraMatrix camera_matrix = p_interface->get_projection_for_eye(p_eye, aspect, camera->znear, camera->zfar); + + // We also ignore our camera position, it will have been positioned with a slightly old tracking position. + // Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo! + Transform world_origin = XRServer::get_singleton()->get_world_origin(); + Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin); + + RID environment = _render_get_environment(p_camera, p_scenario); + + // For stereo render we only prepare for our left eye and then reuse the outcome for our right eye + if (p_eye == XRInterface::EYE_LEFT) { + // Center our transform, we assume basis is equal. + Transform mono_transform = cam_transform; + Transform right_transform = p_interface->get_transform_for_eye(XRInterface::EYE_RIGHT, world_origin); + mono_transform.origin += right_transform.origin; + mono_transform.origin *= 0.5; + + // We need to combine our projection frustums for culling. + // Ideally we should use our clipping planes for this and combine them, + // however our shadow map logic uses our projection matrix. + // Note: as our left and right frustums should be mirrored, we don't need our right projection matrix. + + // - get some base values we need + float eye_dist = (mono_transform.origin - cam_transform.origin).length(); + float z_near = camera_matrix.get_z_near(); // get our near plane + float z_far = camera_matrix.get_z_far(); // get our far plane + float width = (2.0 * z_near) / camera_matrix.matrix[0][0]; + float x_shift = width * camera_matrix.matrix[2][0]; + float height = (2.0 * z_near) / camera_matrix.matrix[1][1]; + float y_shift = height * camera_matrix.matrix[2][1]; + + // printf("Eye_dist = %f, Near = %f, Far = %f, Width = %f, Shift = %f\n", eye_dist, z_near, z_far, width, x_shift); + + // - calculate our near plane size (horizontal only, right_near is mirrored) + float left_near = -eye_dist - ((width - x_shift) * 0.5); + + // - calculate our far plane size (horizontal only, right_far is mirrored) + float left_far = -eye_dist - (z_far * (width - x_shift) * 0.5 / z_near); + float left_far_right_eye = eye_dist - (z_far * (width + x_shift) * 0.5 / z_near); + if (left_far > left_far_right_eye) { + // on displays smaller then double our iod, the right eye far frustrum can overtake the left eyes. + left_far = left_far_right_eye; + } + + // - figure out required z-shift + float slope = (left_far - left_near) / (z_far - z_near); + float z_shift = (left_near / slope) - z_near; + + // - figure out new vertical near plane size (this will be slightly oversized thanks to our z-shift) + float top_near = (height - y_shift) * 0.5; + top_near += (top_near / z_near) * z_shift; + float bottom_near = -(height + y_shift) * 0.5; + bottom_near += (bottom_near / z_near) * z_shift; + + // printf("Left_near = %f, Left_far = %f, Top_near = %f, Bottom_near = %f, Z_shift = %f\n", left_near, left_far, top_near, bottom_near, z_shift); + + // - generate our frustum + CameraMatrix combined_matrix; + combined_matrix.set_frustum(left_near, -left_near, bottom_near, top_near, z_near + z_shift, z_far + z_shift); + + // and finally move our camera back + Transform apply_z_shift; + apply_z_shift.origin = Vector3(0.0, 0.0, z_shift); // z negative is forward so this moves it backwards + mono_transform *= apply_z_shift; + + // now prepare our scene with our adjusted transform projection matrix + _prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold); + } else if (p_eye == XRInterface::EYE_MONO) { + // For mono render, prepare as per usual + _prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), p_screen_lod_threshold); + } + + // And render our scene... + _render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold); +}; + +void RendererSceneCull::_frustum_cull_threaded(uint32_t p_thread, FrustumCullData *cull_data) { + uint32_t cull_total = cull_data->scenario->instance_data.size(); + uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); + uint32_t cull_from = p_thread * cull_total / total_threads; + uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads); + + _frustum_cull(*cull_data, frustum_cull_result_threads[p_thread], cull_from, cull_to); +} + +void RendererSceneCull::_frustum_cull(FrustumCullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to) { + uint64_t frame_number = RSG::rasterizer->get_frame_number(); + float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time(); + + uint32_t sdfgi_last_light_index = 0xFFFFFFFF; + uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF; + + RID instance_pair_buffer[MAX_INSTANCE_PAIRS]; + + for (uint64_t i = p_from; i < p_to; i++) { + bool mesh_visible = false; + + if (cull_data.scenario->instance_aabbs[i].in_frustum(cull_data.cull->frustum)) { + InstanceData &idata = cull_data.scenario->instance_data[i]; + uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK; + + if ((cull_data.visible_layers & idata.layer_mask) == 0) { + //failure + } else if (base_type == RS::INSTANCE_LIGHT) { + cull_result.lights.push_back(idata.instance); + cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid)); + if (cull_data.shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) { + scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later + } + + } else if (base_type == RS::INSTANCE_REFLECTION_PROBE) { + if (cull_data.render_reflection_probe != idata.instance) { + //avoid entering The Matrix + + if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data); + cull_data.cull->lock.lock(); + if (!reflection_probe->update_list.in_list()) { + reflection_probe->render_step = 0; + reflection_probe_render_list.add_last(&reflection_probe->update_list); + } + cull_data.cull->lock.unlock(); + + idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY); + } + + if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) { + cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid)); + } + } + } else if (base_type == RS::INSTANCE_DECAL) { + cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid)); + + } else if (base_type == RS::INSTANCE_GI_PROBE) { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(idata.instance->base_data); + cull_data.cull->lock.lock(); + if (!gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + cull_data.cull->lock.unlock(); + cull_result.gi_probes.push_back(RID::from_uint64(idata.instance_data_rid)); + + } else if (base_type == RS::INSTANCE_LIGHTMAP) { + cull_result.gi_probes.push_back(RID::from_uint64(idata.instance_data_rid)); + } else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) { + bool keep = true; + + if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) { + RenderingServerDefault::redraw_request(); + } + + if (base_type == RS::INSTANCE_MESH) { + mesh_visible = true; + } else if (base_type == RS::INSTANCE_PARTICLES) { + //particles visible? process them + if (RSG::storage->particles_is_inactive(idata.base_rid)) { + //but if nothing is going on, don't do it. + keep = false; + } else { + cull_data.cull->lock.lock(); + RSG::storage->particles_request_process(idata.base_rid); + cull_data.cull->lock.unlock(); + RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized()); + //particles visible? request redraw + RenderingServerDefault::redraw_request(); + } + } + + if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); + uint32_t idx = 0; + + for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); + instance_pair_buffer[idx++] = light->instance; + if (idx == MAX_INSTANCE_PAIRS) { + break; + } + } + + scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx); + idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY); + } + + if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); + uint32_t idx = 0; + + for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data); + + instance_pair_buffer[idx++] = reflection_probe->instance; + if (idx == MAX_INSTANCE_PAIRS) { + break; + } + } + + scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx); + idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY); + } + + if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) { + //InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); + //todo for GLES3 + idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY); + /*for (Set<Instance *>::Element *E = geom->dec.front(); E; E = E->next()) { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data); + + instance_pair_buffer[idx++] = reflection_probe->instance; + if (idx==MAX_INSTANCE_PAIRS) { + break; + } + }*/ + //scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, light_instances, idx); + } + + if (idata.flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); + uint32_t idx = 0; + for (Set<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) { + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data); + + instance_pair_buffer[idx++] = gi_probe->probe_instance; + if (idx == MAX_INSTANCE_PAIRS) { + break; + } + } + + scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx); + idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY); + } + + if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); + Color *sh = idata.instance->lightmap_sh.ptrw(); + const Color *target_sh = idata.instance->lightmap_target_sh.ptr(); + for (uint32_t j = 0; j < 9; j++) { + sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed)); + } + scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh); + idata.instance->last_frame_pass = frame_number; + } + + if (keep) { + cull_result.geometry_instances.push_back(idata.instance_geometry); + } + } + } + + for (uint32_t j = 0; j < cull_data.cull->shadow_count; j++) { + for (uint32_t k = 0; k < cull_data.cull->shadows[j].cascade_count; k++) { + if (cull_data.scenario->instance_aabbs[i].in_frustum(cull_data.cull->shadows[j].cascades[k].frustum)) { + InstanceData &idata = cull_data.scenario->instance_data[i]; + uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK; + + if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) { + cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry); + mesh_visible = true; + } + } + } + } + + for (uint32_t j = 0; j < cull_data.cull->sdfgi.region_count; j++) { + if (cull_data.scenario->instance_aabbs[i].in_aabb(cull_data.cull->sdfgi.region_aabb[j])) { + InstanceData &idata = cull_data.scenario->instance_data[i]; + uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK; + + if (base_type == RS::INSTANCE_LIGHT) { + InstanceLightData *instance_light = (InstanceLightData *)idata.instance->base_data; + if (instance_light->bake_mode == RS::LIGHT_BAKE_STATIC && cull_data.cull->sdfgi.region_cascade[j] <= instance_light->max_sdfgi_cascade) { + if (sdfgi_last_light_index != i || sdfgi_last_light_cascade != cull_data.cull->sdfgi.region_cascade[j]) { + sdfgi_last_light_index = i; + sdfgi_last_light_cascade = cull_data.cull->sdfgi.region_cascade[j]; + cull_result.sdfgi_cascade_lights[sdfgi_last_light_cascade].push_back(instance_light->instance); + } + } + } else if ((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) { + if (idata.flags & InstanceData::FLAG_USES_BAKED_LIGHT) { + cull_result.sdfgi_region_geometry_instances[j].push_back(idata.instance_geometry); + mesh_visible = true; + } + } + } + } + + if (mesh_visible && cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_USES_MESH_INSTANCE) { + cull_result.mesh_instances.push_back(cull_data.scenario->instance_data[i].instance->mesh_instance); + } + } +} + +void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows) { + // Note, in stereo rendering: + // - p_cam_transform will be a transform in the middle of our two eyes + // - p_cam_projection is a wider frustrum that encompasses both eyes + + Instance *render_reflection_probe = instance_owner.getornull(p_reflection_probe); //if null, not rendering to it + + Scenario *scenario = scenario_owner.getornull(p_scenario); + + render_pass++; + + scene_render->set_scene_pass(render_pass); + + if (p_render_buffers.is_valid()) { + scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not) + } + + RENDER_TIMESTAMP("Frustum Culling"); + + //rasterizer->set_camera(camera->transform, camera_matrix,ortho); + + Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform); + + Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized()); + + /* STEP 2 - CULL */ + + cull.frustum = Frustum(planes); + + Vector<RID> directional_lights; + // directional lights + { + cull.shadow_count = 0; + + Vector<Instance *> lights_with_shadow; + + for (List<Instance *>::Element *E = scenario->directional_lights.front(); E; E = E->next()) { + if (!E->get()->visible) { + continue; + } + + if (directional_lights.size() > RendererSceneRender::MAX_DIRECTIONAL_LIGHTS) { + break; + } + + InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); + + //check shadow.. + + if (light) { + if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base) && !(RSG::storage->light_get_type(E->get()->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->get()->base))) { + lights_with_shadow.push_back(E->get()); + } + //add to list + directional_lights.push_back(light->instance); + } + } + + scene_render->set_directional_shadow_count(lights_with_shadow.size()); + + for (int i = 0; i < lights_with_shadow.size(); i++) { + _light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect); + } + } + + { //sdfgi + cull.sdfgi.region_count = 0; + + if (p_render_buffers.is_valid()) { + cull.sdfgi.cascade_light_count = 0; + + uint32_t prev_cascade = 0xFFFFFFFF; + uint32_t pending_region_count = scene_render->sdfgi_get_pending_region_count(p_render_buffers); + + for (uint32_t i = 0; i < pending_region_count; i++) { + cull.sdfgi.region_aabb[i] = scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i); + uint32_t region_cascade = scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i); + cull.sdfgi.region_cascade[i] = region_cascade; + + if (region_cascade != prev_cascade) { + cull.sdfgi.cascade_light_index[cull.sdfgi.cascade_light_count] = region_cascade; + cull.sdfgi.cascade_light_count++; + prev_cascade = region_cascade; + } + } + + cull.sdfgi.region_count = pending_region_count; + } + } + + frustum_cull_result.clear(); + + { + uint64_t cull_from = 0; + uint64_t cull_to = scenario->instance_data.size(); + + FrustumCullData cull_data; + + //prepare for eventual thread usage + cull_data.cull = &cull; + cull_data.scenario = scenario; + cull_data.shadow_atlas = p_shadow_atlas; + cull_data.cam_transform = p_cam_transform; + cull_data.visible_layers = p_visible_layers; + cull_data.render_reflection_probe = render_reflection_probe; +//#define DEBUG_CULL_TIME +#ifdef DEBUG_CULL_TIME + uint64_t time_from = OS::get_singleton()->get_ticks_usec(); +#endif + if (cull_to > thread_cull_threshold) { + //multiple threads + for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) { + frustum_cull_result_threads[i].clear(); + } + + RendererThreadPool::singleton->thread_work_pool.do_work(frustum_cull_result_threads.size(), this, &RendererSceneCull::_frustum_cull_threaded, &cull_data); + + for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) { + frustum_cull_result.append_from(frustum_cull_result_threads[i]); + } + + } else { + //single threaded + _frustum_cull(cull_data, frustum_cull_result, cull_from, cull_to); + } + +#ifdef DEBUG_CULL_TIME + static float time_avg = 0; + static uint32_t time_count = 0; + time_avg += double(OS::get_singleton()->get_ticks_usec() - time_from) / 1000.0; + time_count++; + print_line("time taken: " + rtos(time_avg / time_count)); +#endif + + if (frustum_cull_result.mesh_instances.size()) { + for (uint64_t i = 0; i < frustum_cull_result.mesh_instances.size(); i++) { + RSG::storage->mesh_instance_check_for_update(frustum_cull_result.mesh_instances[i]); + } + RSG::storage->update_mesh_instances(); + } + } + + //render shadows + + for (uint32_t i = 0; i < cull.shadow_count; i++) { + for (uint32_t j = 0; j < cull.shadows[i].cascade_count; j++) { + const Cull::Shadow::Cascade &c = cull.shadows[i].cascades[j]; + // print_line("shadow " + itos(i) + " cascade " + itos(j) + " elements: " + itos(c.cull_result.size())); + scene_render->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale); + scene_render->render_shadow(cull.shadows[i].light_instance, p_shadow_atlas, j, frustum_cull_result.directional_shadows[i].cascade_geometry_instances[j], near_plane, p_cam_projection.get_lod_multiplier(), p_screen_lod_threshold); + } + } + + //render SDFGI + + { + if (cull.sdfgi.region_count > 0) { + //update regions + for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) { + scene_render->render_sdfgi(p_render_buffers, i, frustum_cull_result.sdfgi_region_geometry_instances[i]); + } + //check if static lights were culled + bool static_lights_culled = false; + for (uint32_t i = 0; i < cull.sdfgi.cascade_light_count; i++) { + if (frustum_cull_result.sdfgi_cascade_lights[i].size()) { + static_lights_culled = true; + break; + } + } + + if (static_lights_culled) { + scene_render->render_sdfgi_static_lights(p_render_buffers, cull.sdfgi.cascade_light_count, cull.sdfgi.cascade_light_index, frustum_cull_result.sdfgi_cascade_lights); + } + } + + if (p_render_buffers.is_valid()) { + scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_lights, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size()); + } + } + + //light_samplers_culled=0; + + /* + print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); + print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); + print_line("OTE: "+itos(p_scenario->octree.get_elem_count())); + print_line("OTP: "+itos(p_scenario->octree.get_pair_count())); + */ + + /* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */ + //removed, will replace with culling + + /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */ + + /* STEP 5 - PROCESS POSITIONAL LIGHTS */ + + if (p_using_shadows) { //setup shadow maps + + //SortArray<Instance*,_InstanceLightsort> sorter; + //sorter.sort(light_cull_result,light_cull_count); + for (uint32_t i = 0; i < (uint32_t)frustum_cull_result.lights.size(); i++) { + Instance *ins = frustum_cull_result.lights[i]; + + if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) { + continue; + } + + InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data); + + float coverage = 0.f; + + { //compute coverage + + Transform cam_xf = p_cam_transform; + float zn = p_cam_projection.get_z_near(); + Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane + + // near plane half width and height + Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents(); + + switch (RSG::storage->light_get_type(ins->base)) { + case RS::LIGHT_OMNI: { + float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE); + + //get two points parallel to near plane + Vector3 points[2] = { + ins->transform.origin, + ins->transform.origin + cam_xf.basis.get_axis(0) * radius + }; + + if (!p_cam_orthogonal) { + //if using perspetive, map them to near plane + for (int j = 0; j < 2; j++) { + if (p.distance_to(points[j]) < 0) { + points[j].z = -zn; //small hack to keep size constant when hitting the screen + } + + p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane + } + } + + float screen_diameter = points[0].distance_to(points[1]) * 2; + coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y); + } break; + case RS::LIGHT_SPOT: { + float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE); + float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE); + + float w = radius * Math::sin(Math::deg2rad(angle)); + float d = radius * Math::cos(Math::deg2rad(angle)); + + Vector3 base = ins->transform.origin - ins->transform.basis.get_axis(2).normalized() * d; + + Vector3 points[2] = { + base, + base + cam_xf.basis.get_axis(0) * w + }; + + if (!p_cam_orthogonal) { + //if using perspetive, map them to near plane + for (int j = 0; j < 2; j++) { + if (p.distance_to(points[j]) < 0) { + points[j].z = -zn; //small hack to keep size constant when hitting the screen + } + + p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane + } + } + + float screen_diameter = points[0].distance_to(points[1]) * 2; + coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y); + + } break; + default: { + ERR_PRINT("Invalid Light Type"); + } + } + } + + if (light->shadow_dirty) { + light->last_version++; + light->shadow_dirty = false; + } + + bool redraw = scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version); + + if (redraw) { + //must redraw! + RENDER_TIMESTAMP(">Rendering Light " + itos(i)); + light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario, p_screen_lod_threshold); + RENDER_TIMESTAMP("<Rendering Light " + itos(i)); + } + } + } + + //append the directional lights to the lights culled + for (int i = 0; i < directional_lights.size(); i++) { + frustum_cull_result.light_instances.push_back(directional_lights[i]); + } +} + +RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) { + Camera *camera = camera_owner.getornull(p_camera); + if (camera && scene_render->is_environment(camera->env)) { + return camera->env; + } + + Scenario *scenario = scenario_owner.getornull(p_scenario); + if (!scenario) { + return RID(); + } + if (scene_render->is_environment(scenario->environment)) { + return scenario->environment; + } + + if (scene_render->is_environment(scenario->fallback_environment)) { + return scenario->fallback_environment; + } + + return RID(); +} + +void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + + RID camera_effects; + if (p_force_camera_effects.is_valid()) { + camera_effects = p_force_camera_effects; + } else { + camera_effects = scenario->camera_effects; + } + /* PROCESS GEOMETRY AND DRAW SCENE */ + + RENDER_TIMESTAMP("Render Scene "); + scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, frustum_cull_result.geometry_instances, frustum_cull_result.light_instances, frustum_cull_result.reflections, frustum_cull_result.gi_probes, frustum_cull_result.decals, frustum_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold); +} + +void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) { +#ifndef _3D_DISABLED + + Scenario *scenario = scenario_owner.getornull(p_scenario); + + RID environment; + if (scenario->environment.is_valid()) { + environment = scenario->environment; + } else { + environment = scenario->fallback_environment; + } + RENDER_TIMESTAMP("Render Empty Scene "); + scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0); +#endif +} + +bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int p_step) { + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data); + Scenario *scenario = p_instance->scenario; + ERR_FAIL_COND_V(!scenario, true); + + RenderingServerDefault::redraw_request(); //update, so it updates in editor + + if (p_step == 0) { + if (!scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) { + return true; //all full + } + } + + if (p_step >= 0 && p_step < 6) { + static const Vector3 view_normals[6] = { + Vector3(+1, 0, 0), + Vector3(-1, 0, 0), + Vector3(0, +1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1) + }; + static const Vector3 view_up[6] = { + Vector3(0, -1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1), + Vector3(0, -1, 0), + Vector3(0, -1, 0) + }; + + Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base); + Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base); + float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base); + float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas); + float lod_threshold = RSG::storage->reflection_probe_get_lod_threshold(p_instance->base) / size; + + Vector3 edge = view_normals[p_step] * extents; + float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit + + max_distance = MAX(max_distance, distance); + + //render cubemap side + CameraMatrix cm; + cm.set_perspective(90, 1, 0.01, max_distance); + + Transform local_view; + local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]); + + Transform xform = p_instance->transform * local_view; + + RID shadow_atlas; + + bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base); + if (use_shadows) { + shadow_atlas = scenario->reflection_probe_shadow_atlas; + } + + RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step)); + _prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, lod_threshold, use_shadows); + _render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step, lod_threshold); + + } else { + //do roughness postprocess step until it believes it's done + RENDER_TIMESTAMP("Post-Process Reflection Probe, Step " + itos(p_step)); + return scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); + } + + return false; +} + +void RendererSceneCull::render_probes() { + /* REFLECTION PROBES */ + + SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first(); + + bool busy = false; + + while (ref_probe) { + SelfList<InstanceReflectionProbeData> *next = ref_probe->next(); + RID base = ref_probe->self()->owner->base; + + switch (RSG::storage->reflection_probe_get_update_mode(base)) { + case RS::REFLECTION_PROBE_UPDATE_ONCE: { + if (busy) { //already rendering something + break; + } + + bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step); + if (done) { + reflection_probe_render_list.remove(ref_probe); + } else { + ref_probe->self()->render_step++; + } + + busy = true; //do not render another one of this kind + } break; + case RS::REFLECTION_PROBE_UPDATE_ALWAYS: { + int step = 0; + bool done = false; + while (!done) { + done = _render_reflection_probe_step(ref_probe->self()->owner, step); + step++; + } + + reflection_probe_render_list.remove(ref_probe); + } break; + } + + ref_probe = next; + } + + /* GI PROBES */ + + SelfList<InstanceGIProbeData> *gi_probe = gi_probe_update_list.first(); + + if (gi_probe) { + RENDER_TIMESTAMP("Render GI Probes"); + } + + while (gi_probe) { + SelfList<InstanceGIProbeData> *next = gi_probe->next(); + + InstanceGIProbeData *probe = gi_probe->self(); + //Instance *instance_probe = probe->owner; + + //check if probe must be setup, but don't do if on the lighting thread + + bool cache_dirty = false; + int cache_count = 0; + { + int light_cache_size = probe->light_cache.size(); + const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr(); + const RID *instance_caches = probe->light_instances.ptr(); + + int idx = 0; //must count visible lights + for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { + Instance *instance = E->get(); + InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; + if (!instance->visible) { + continue; + } + if (cache_dirty) { + //do nothing, since idx must count all visible lights anyway + } else if (idx >= light_cache_size) { + cache_dirty = true; + } else { + const InstanceGIProbeData::LightCache *cache = &caches[idx]; + + if ( + instance_caches[idx] != instance_light->instance || + cache->has_shadow != RSG::storage->light_has_shadow(instance->base) || + cache->type != RSG::storage->light_get_type(instance->base) || + cache->transform != instance->transform || + cache->color != RSG::storage->light_get_color(instance->base) || + cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) || + cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) || + cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) || + cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) || + cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) || + cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) { + cache_dirty = true; + } + } + + idx++; + } + + for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) { + Instance *instance = E->get(); + InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; + if (!instance->visible) { + continue; + } + if (cache_dirty) { + //do nothing, since idx must count all visible lights anyway + } else if (idx >= light_cache_size) { + cache_dirty = true; + } else { + const InstanceGIProbeData::LightCache *cache = &caches[idx]; + + if ( + instance_caches[idx] != instance_light->instance || + cache->has_shadow != RSG::storage->light_has_shadow(instance->base) || + cache->type != RSG::storage->light_get_type(instance->base) || + cache->transform != instance->transform || + cache->color != RSG::storage->light_get_color(instance->base) || + cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) || + cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) || + cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) || + cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) || + cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) || + cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) || + cache->sky_only != RSG::storage->light_directional_is_sky_only(instance->base)) { + cache_dirty = true; + } + } + + idx++; + } + + if (idx != light_cache_size) { + cache_dirty = true; + } + + cache_count = idx; + } + + bool update_lights = scene_render->gi_probe_needs_update(probe->probe_instance); + + if (cache_dirty) { + probe->light_cache.resize(cache_count); + probe->light_instances.resize(cache_count); + + if (cache_count) { + InstanceGIProbeData::LightCache *caches = probe->light_cache.ptrw(); + RID *instance_caches = probe->light_instances.ptrw(); + + int idx = 0; //must count visible lights + for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { + Instance *instance = E->get(); + InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; + if (!instance->visible) { + continue; + } + + InstanceGIProbeData::LightCache *cache = &caches[idx]; + + instance_caches[idx] = instance_light->instance; + cache->has_shadow = RSG::storage->light_has_shadow(instance->base); + cache->type = RSG::storage->light_get_type(instance->base); + cache->transform = instance->transform; + cache->color = RSG::storage->light_get_color(instance->base); + cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY); + cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY); + cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE); + cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION); + cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); + cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + idx++; + } + for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) { + Instance *instance = E->get(); + InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; + if (!instance->visible) { + continue; + } + + InstanceGIProbeData::LightCache *cache = &caches[idx]; + + instance_caches[idx] = instance_light->instance; + cache->has_shadow = RSG::storage->light_has_shadow(instance->base); + cache->type = RSG::storage->light_get_type(instance->base); + cache->transform = instance->transform; + cache->color = RSG::storage->light_get_color(instance->base); + cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY); + cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY); + cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE); + cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION); + cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); + cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION); + cache->sky_only = RSG::storage->light_directional_is_sky_only(instance->base); + + idx++; + } + } + + update_lights = true; + } + + frustum_cull_result.geometry_instances.clear(); + + RID instance_pair_buffer[MAX_INSTANCE_PAIRS]; + + for (Set<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) { + Instance *ins = E->get(); + if (!ins->visible) { + continue; + } + InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data; + + if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY)) { + uint32_t idx = 0; + for (Set<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) { + InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data); + + instance_pair_buffer[idx++] = gi_probe2->probe_instance; + if (idx == MAX_INSTANCE_PAIRS) { + break; + } + } + + scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx); + + ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY); + } + + frustum_cull_result.geometry_instances.push_back(geom->geometry_instance); + } + + scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, frustum_cull_result.geometry_instances); + + gi_probe_update_list.remove(gi_probe); + + gi_probe = next; + } +} + +void RendererSceneCull::render_particle_colliders() { + while (heightfield_particle_colliders_update_list.front()) { + Instance *hfpc = heightfield_particle_colliders_update_list.front()->get(); + + if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) { + //update heightfield + instance_cull_result.clear(); + frustum_cull_result.geometry_instances.clear(); + + struct CullAABB { + PagedArray<Instance *> *result; + _FORCE_INLINE_ bool operator()(void *p_data) { + Instance *p_instance = (Instance *)p_data; + result->push_back(p_instance); + return false; + } + }; + + CullAABB cull_aabb; + cull_aabb.result = &instance_cull_result; + hfpc->scenario->indexers[Scenario::INDEXER_GEOMETRY].aabb_query(hfpc->transformed_aabb, cull_aabb); + hfpc->scenario->indexers[Scenario::INDEXER_VOLUMES].aabb_query(hfpc->transformed_aabb, cull_aabb); + + for (int i = 0; i < (int)instance_cull_result.size(); i++) { + Instance *instance = instance_cull_result[i]; + if (!instance || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision + continue; + } + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); + frustum_cull_result.geometry_instances.push_back(geom->geometry_instance); + } + + scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, frustum_cull_result.geometry_instances); + } + heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front()); + } +} + +void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { + List<RendererStorage::InstanceShaderParam> plist; + RSG::storage->material_get_instance_shader_parameters(p_material, &plist); + for (List<RendererStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) { + StringName name = E->get().info.name; + if (isparams.has(name)) { + if (isparams[name].info.type != E->get().info.type) { + WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different data types. Only the first one (in order) will display correctly."); + } + if (isparams[name].index != E->get().index) { + WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different indices. Only the first one (in order) will display correctly."); + } + continue; //first one found always has priority + } + + Instance::InstanceShaderParameter isp; + isp.index = E->get().index; + isp.info = E->get().info; + isp.default_value = E->get().default_value; + if (existing_isparams.has(name)) { + isp.value = existing_isparams[name].value; + } else { + isp.value = E->get().default_value; + } + isparams[name] = isp; + } +} + +void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { + if (p_instance->update_aabb) { + _update_instance_aabb(p_instance); + } + + if (p_instance->update_dependencies) { + p_instance->dependency_tracker.update_begin(); + + if (p_instance->base.is_valid()) { + RSG::storage->base_update_dependency(p_instance->base, &p_instance->dependency_tracker); + } + + if (p_instance->material_override.is_valid()) { + RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker); + } + + if (p_instance->base_type == RS::INSTANCE_MESH) { + //remove materials no longer used and un-own them + + int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base); + p_instance->materials.resize(new_mat_count); + + _instance_update_mesh_instance(p_instance); + } + + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); + + bool can_cast_shadows = true; + bool is_animated = false; + Map<StringName, Instance::InstanceShaderParameter> isparams; + + if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) { + can_cast_shadows = false; + } + + if (p_instance->material_override.is_valid()) { + if (!RSG::storage->material_casts_shadows(p_instance->material_override)) { + can_cast_shadows = false; + } + is_animated = RSG::storage->material_is_animated(p_instance->material_override); + _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override); + } else { + if (p_instance->base_type == RS::INSTANCE_MESH) { + RID mesh = p_instance->base; + + if (mesh.is_valid()) { + bool cast_shadows = false; + + for (int i = 0; i < p_instance->materials.size(); i++) { + RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i); + + if (!mat.is_valid()) { + cast_shadows = true; + } else { + if (RSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + + if (RSG::storage->material_is_animated(mat)) { + is_animated = true; + } + + _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); + + RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + } + + } else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) { + RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base); + if (mesh.is_valid()) { + bool cast_shadows = false; + + int sc = RSG::storage->mesh_get_surface_count(mesh); + for (int i = 0; i < sc; i++) { + RID mat = RSG::storage->mesh_surface_get_material(mesh, i); + + if (!mat.is_valid()) { + cast_shadows = true; + + } else { + if (RSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + if (RSG::storage->material_is_animated(mat)) { + is_animated = true; + } + + _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); + + RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + + RSG::storage->base_update_dependency(mesh, &p_instance->dependency_tracker); + } + } else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) { + RID mat = RSG::storage->immediate_get_material(p_instance->base); + + if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) { + can_cast_shadows = false; + } + + if (mat.is_valid() && RSG::storage->material_is_animated(mat)) { + is_animated = true; + } + + if (mat.is_valid()) { + _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); + } + + if (mat.is_valid()) { + RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + } + + } else if (p_instance->base_type == RS::INSTANCE_PARTICLES) { + bool cast_shadows = false; + + int dp = RSG::storage->particles_get_draw_passes(p_instance->base); + + for (int i = 0; i < dp; i++) { + RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i); + if (!mesh.is_valid()) { + continue; + } + + int sc = RSG::storage->mesh_get_surface_count(mesh); + for (int j = 0; j < sc; j++) { + RID mat = RSG::storage->mesh_surface_get_material(mesh, j); + + if (!mat.is_valid()) { + cast_shadows = true; + } else { + if (RSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + + if (RSG::storage->material_is_animated(mat)) { + is_animated = true; + } + + _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); + + RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker); + } + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + } + } + + if (can_cast_shadows != geom->can_cast_shadows) { + //ability to cast shadows change, let lights now + for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) { + InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); + light->shadow_dirty = true; + } + + geom->can_cast_shadows = can_cast_shadows; + } + + geom->material_is_animated = is_animated; + p_instance->instance_shader_parameters = isparams; + + if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) { + p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0); + if (p_instance->instance_allocated_shader_parameters) { + p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self); + scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset); + + for (Map<StringName, Instance::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) { + if (E->get().value.get_type() != Variant::NIL) { + RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value); + } + } + } else { + RSG::storage->global_variables_instance_free(p_instance->self); + p_instance->instance_allocated_shader_parameters_offset = -1; + scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1); + } + } + } + + if (p_instance->skeleton.is_valid()) { + RSG::storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker); + } + + p_instance->dependency_tracker.update_end(); + + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); + scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, p_instance->materials); + } + } + + _instance_update_list.remove(&p_instance->update_item); + + _update_instance(p_instance); + + p_instance->update_aabb = false; + p_instance->update_dependencies = false; +} + +void RendererSceneCull::update_dirty_instances() { + RSG::storage->update_dirty_resources(); + + while (_instance_update_list.first()) { + _update_dirty_instance(_instance_update_list.first()->self()); + } +} + +void RendererSceneCull::update() { + //optimize bvhs + for (uint32_t i = 0; i < scenario_owner.get_rid_count(); i++) { + Scenario *s = scenario_owner.get_ptr_by_index(i); + s->indexers[Scenario::INDEXER_GEOMETRY].optimize_incremental(indexer_update_iterations); + s->indexers[Scenario::INDEXER_VOLUMES].optimize_incremental(indexer_update_iterations); + } + scene_render->update(); + update_dirty_instances(); + render_particle_colliders(); +} + +bool RendererSceneCull::free(RID p_rid) { + if (scene_render->free(p_rid)) { + return true; + } + + if (camera_owner.owns(p_rid)) { + Camera *camera = camera_owner.getornull(p_rid); + + camera_owner.free(p_rid); + memdelete(camera); + + } else if (scenario_owner.owns(p_rid)) { + Scenario *scenario = scenario_owner.getornull(p_rid); + + while (scenario->instances.first()) { + instance_set_scenario(scenario->instances.first()->self()->self, RID()); + } + scenario->instance_aabbs.reset(); + scenario->instance_data.reset(); + + scene_render->free(scenario->reflection_probe_shadow_atlas); + scene_render->free(scenario->reflection_atlas); + scenario_owner.free(p_rid); + memdelete(scenario); + + } else if (instance_owner.owns(p_rid)) { + // delete the instance + + update_dirty_instances(); + + Instance *instance = instance_owner.getornull(p_rid); + + instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0); + instance_set_scenario(p_rid, RID()); + instance_set_base(p_rid, RID()); + instance_geometry_set_material_override(p_rid, RID()); + instance_attach_skeleton(p_rid, RID()); + + if (instance->instance_allocated_shader_parameters) { + //free the used shader parameters + RSG::storage->global_variables_instance_free(instance->self); + } + update_dirty_instances(); //in case something changed this + + instance_owner.free(p_rid); + memdelete(instance); + } else { + return false; + } + + return true; +} + +TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) { + return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size); +} + +/*******************************/ +/* Passthrough to Scene Render */ +/*******************************/ + +/* ENVIRONMENT API */ + +RendererSceneCull *RendererSceneCull::singleton = nullptr; + +void RendererSceneCull::set_scene_render(RendererSceneRender *p_scene_render) { + scene_render = p_scene_render; + geometry_instance_pair_mask = scene_render->geometry_instance_get_pair_mask(); +} + +RendererSceneCull::RendererSceneCull() { + render_pass = 1; + singleton = this; + + instance_cull_result.set_page_pool(&instance_cull_page_pool); + instance_shadow_cull_result.set_page_pool(&instance_cull_page_pool); + + geometry_instances_to_shadow_render.set_page_pool(&geometry_instance_cull_page_pool); + + frustum_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); + frustum_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); + for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) { + frustum_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); + } + + indexer_update_iterations = GLOBAL_GET("rendering/spatial_indexer/update_iterations_per_frame"); + thread_cull_threshold = GLOBAL_GET("rendering/spatial_indexer/threaded_cull_minimum_instances"); + thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)RendererThreadPool::singleton->thread_work_pool.get_thread_count()); //make sure there is at least one thread per CPU +} + +RendererSceneCull::~RendererSceneCull() { + instance_cull_result.reset(); + instance_shadow_cull_result.reset(); + + geometry_instances_to_shadow_render.reset(); + + frustum_cull_result.reset(); + for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) { + frustum_cull_result_threads[i].reset(); + } + frustum_cull_result_threads.clear(); +} diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h new file mode 100644 index 0000000000..796fb14743 --- /dev/null +++ b/servers/rendering/renderer_scene_cull.h @@ -0,0 +1,1045 @@ +/*************************************************************************/ +/* renderer_scene_cull.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RENDERING_SERVER_SCENE_CULL_H +#define RENDERING_SERVER_SCENE_CULL_H + +#include "core/templates/pass_func.h" +#include "servers/rendering/renderer_compositor.h" + +#include "core/math/dynamic_bvh.h" +#include "core/math/geometry_3d.h" +#include "core/math/octree.h" +#include "core/os/semaphore.h" +#include "core/os/thread.h" +#include "core/templates/local_vector.h" +#include "core/templates/paged_allocator.h" +#include "core/templates/paged_array.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" +#include "servers/rendering/renderer_scene.h" +#include "servers/rendering/renderer_scene_render.h" +#include "servers/xr/xr_interface.h" +class RendererSceneCull : public RendererScene { +public: + RendererSceneRender *scene_render; + + enum { + SDFGI_MAX_CASCADES = 8, + SDFGI_MAX_REGIONS_PER_CASCADE = 3, + MAX_INSTANCE_PAIRS = 32 + }; + + uint64_t render_pass; + + static RendererSceneCull *singleton; + + /* CAMERA API */ + + struct Camera { + enum Type { + PERSPECTIVE, + ORTHOGONAL, + FRUSTUM + }; + Type type; + float fov; + float znear, zfar; + float size; + Vector2 offset; + uint32_t visible_layers; + bool vaspect; + RID env; + RID effects; + + Transform transform; + + Camera() { + visible_layers = 0xFFFFFFFF; + fov = 75; + type = PERSPECTIVE; + znear = 0.05; + zfar = 4000; + size = 1.0; + offset = Vector2(); + vaspect = false; + } + }; + + mutable RID_PtrOwner<Camera> camera_owner; + + virtual RID camera_create(); + virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far); + virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); + virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far); + virtual void camera_set_transform(RID p_camera, const Transform &p_transform); + virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers); + virtual void camera_set_environment(RID p_camera, RID p_env); + virtual void camera_set_camera_effects(RID p_camera, RID p_fx); + virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable); + virtual bool is_camera(RID p_camera) const; + + /* SCENARIO API */ + + struct Instance; + + struct PlaneSign { + _ALWAYS_INLINE_ PlaneSign() {} + _ALWAYS_INLINE_ PlaneSign(const Plane &p_plane) { + if (p_plane.normal.x > 0) { + signs[0] = 0; + } else { + signs[0] = 3; + } + if (p_plane.normal.y > 0) { + signs[1] = 1; + } else { + signs[1] = 4; + } + if (p_plane.normal.z > 0) { + signs[2] = 2; + } else { + signs[2] = 5; + } + } + + uint32_t signs[3]; + }; + + struct Frustum { + Vector<Plane> planes; + Vector<PlaneSign> plane_signs; + const Plane *planes_ptr; + const PlaneSign *plane_signs_ptr; + uint32_t plane_count; + + _ALWAYS_INLINE_ Frustum() {} + _ALWAYS_INLINE_ Frustum(const Frustum &p_frustum) { + planes = p_frustum.planes; + plane_signs = p_frustum.plane_signs; + + planes_ptr = planes.ptr(); + plane_signs_ptr = plane_signs.ptr(); + plane_count = p_frustum.plane_count; + } + _ALWAYS_INLINE_ void operator=(const Frustum &p_frustum) { + planes = p_frustum.planes; + plane_signs = p_frustum.plane_signs; + + planes_ptr = planes.ptr(); + plane_signs_ptr = plane_signs.ptr(); + plane_count = p_frustum.plane_count; + } + _ALWAYS_INLINE_ Frustum(const Vector<Plane> &p_planes) { + planes = p_planes; + planes_ptr = planes.ptrw(); + plane_count = planes.size(); + for (int i = 0; i < planes.size(); i++) { + PlaneSign ps(p_planes[i]); + plane_signs.push_back(ps); + } + + plane_signs_ptr = plane_signs.ptr(); + } + }; + + struct InstanceBounds { + // Efficiently store instance bounds. + // Because bounds checking is performed first, + // keep it separated from data. + + real_t bounds[6]; + _ALWAYS_INLINE_ InstanceBounds() {} + + _ALWAYS_INLINE_ InstanceBounds(const AABB &p_aabb) { + bounds[0] = p_aabb.position.x; + bounds[1] = p_aabb.position.y; + bounds[2] = p_aabb.position.z; + bounds[3] = p_aabb.position.x + p_aabb.size.x; + bounds[4] = p_aabb.position.y + p_aabb.size.y; + bounds[5] = p_aabb.position.z + p_aabb.size.z; + } + _ALWAYS_INLINE_ bool in_frustum(const Frustum &p_frustum) const { + // This is not a full SAT check and the possibility of false positives exist, + // but the tradeoff vs performance is still very good. + + for (uint32_t i = 0; i < p_frustum.plane_count; i++) { + Vector3 min( + bounds[p_frustum.plane_signs_ptr[i].signs[0]], + bounds[p_frustum.plane_signs_ptr[i].signs[1]], + bounds[p_frustum.plane_signs_ptr[i].signs[2]]); + + if (p_frustum.planes_ptr[i].distance_to(min) >= 0.0) { + return false; + } + } + + return true; + } + _ALWAYS_INLINE_ bool in_aabb(const AABB &p_aabb) const { + Vector3 end = p_aabb.position + p_aabb.size; + + if (bounds[0] >= end.x) { + return false; + } + if (bounds[3] <= p_aabb.position.x) { + return false; + } + if (bounds[1] >= end.y) { + return false; + } + if (bounds[4] <= p_aabb.position.y) { + return false; + } + if (bounds[2] >= end.z) { + return false; + } + if (bounds[5] <= p_aabb.position.z) { + return false; + } + + return true; + } + }; + + struct InstanceData { + // Store instance pointer as well as common instance processing information, + // to make processing more cache friendly. + enum Flags { + FLAG_BASE_TYPE_MASK = 0xFF, + FLAG_CAST_SHADOWS = (1 << 8), + FLAG_CAST_SHADOWS_ONLY = (1 << 9), + FLAG_REDRAW_IF_VISIBLE = (1 << 10), + FLAG_GEOM_LIGHTING_DIRTY = (1 << 11), + FLAG_GEOM_REFLECTION_DIRTY = (1 << 12), + FLAG_GEOM_DECAL_DIRTY = (1 << 13), + FLAG_GEOM_GI_PROBE_DIRTY = (1 << 14), + FLAG_LIGHTMAP_CAPTURE = (1 << 15), + FLAG_USES_BAKED_LIGHT = (1 << 16), + FLAG_USES_MESH_INSTANCE = (1 << 17), + FLAG_REFLECTION_PROBE_DIRTY = (1 << 18), + }; + + uint32_t flags = 0; + uint32_t layer_mask = 0; //for fast layer-mask discard + RID base_rid; + union { + uint64_t instance_data_rid; + RendererSceneRender::GeometryInstance *instance_geometry; + }; + Instance *instance = nullptr; + }; + + PagedArrayPool<InstanceBounds> instance_aabb_page_pool; + PagedArrayPool<InstanceData> instance_data_page_pool; + + struct Scenario { + enum IndexerType { + INDEXER_GEOMETRY, //for geometry + INDEXER_VOLUMES, //for everything else + INDEXER_MAX + }; + + DynamicBVH indexers[INDEXER_MAX]; + + RS::ScenarioDebugMode debug; + RID self; + + List<Instance *> directional_lights; + RID environment; + RID fallback_environment; + RID camera_effects; + RID reflection_probe_shadow_atlas; + RID reflection_atlas; + + SelfList<Instance>::List instances; + + LocalVector<RID> dynamic_lights; + + PagedArray<InstanceBounds> instance_aabbs; + PagedArray<InstanceData> instance_data; + + Scenario() { + indexers[INDEXER_GEOMETRY].set_index(INDEXER_GEOMETRY); + indexers[INDEXER_VOLUMES].set_index(INDEXER_VOLUMES); + debug = RS::SCENARIO_DEBUG_DISABLED; + } + }; + + int indexer_update_iterations = 0; + + mutable RID_PtrOwner<Scenario> scenario_owner; + + static void _instance_pair(Instance *p_A, Instance *p_B); + static void _instance_unpair(Instance *p_A, Instance *p_B); + + void _instance_update_mesh_instance(Instance *p_instance); + + virtual RID scenario_create(); + + virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode); + virtual void scenario_set_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx); + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count); + virtual bool is_scenario(RID p_scenario) const; + virtual RID scenario_get_environment(RID p_scenario); + + /* INSTANCING API */ + + struct InstancePair { + Instance *a; + Instance *b; + SelfList<InstancePair> list_a; + SelfList<InstancePair> list_b; + InstancePair() : + list_a(this), list_b(this) {} + }; + + PagedAllocator<InstancePair> pair_allocator; + + struct InstanceBaseData { + virtual ~InstanceBaseData() {} + }; + + struct Instance { + RS::InstanceType base_type; + RID base; + + RID skeleton; + RID material_override; + + RID mesh_instance; //only used for meshes and when skeleton/blendshapes exist + + Transform transform; + + float lod_bias; + + Vector<RID> materials; + + RS::ShadowCastingSetting cast_shadows; + + uint32_t layer_mask; + //fit in 32 bits + bool mirror : 8; + bool receive_shadows : 8; + bool visible : 8; + bool baked_light : 2; //this flag is only to know if it actually did use baked light + bool dynamic_gi : 2; //same above for dynamic objects + bool redraw_if_visible : 4; + + Instance *lightmap; + Rect2 lightmap_uv_scale; + int lightmap_slice_index; + uint32_t lightmap_cull_index; + Vector<Color> lightmap_sh; //spherical harmonic + + AABB aabb; + AABB transformed_aabb; + AABB prev_transformed_aabb; + + struct InstanceShaderParameter { + int32_t index = -1; + Variant value; + Variant default_value; + PropertyInfo info; + }; + + Map<StringName, InstanceShaderParameter> instance_shader_parameters; + bool instance_allocated_shader_parameters = false; + int32_t instance_allocated_shader_parameters_offset = -1; + + // + + RID self; + //scenario stuff + DynamicBVH::ID indexer_id; + int32_t array_index; + Scenario *scenario; + SelfList<Instance> scenario_item; + + //aabb stuff + bool update_aabb; + bool update_dependencies; + + SelfList<Instance> update_item; + + AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better? + float extra_margin; + ObjectID object_id; + + float lod_begin; + float lod_end; + float lod_begin_hysteresis; + float lod_end_hysteresis; + RID lod_instance; + + Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior + + uint64_t last_frame_pass; + + uint64_t version; // changes to this, and changes to base increase version + + InstanceBaseData *base_data; + + SelfList<InstancePair>::List pairs; + uint64_t pair_check; + + RendererStorage::DependencyTracker dependency_tracker; + + static void dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *tracker) { + Instance *instance = (Instance *)tracker->userdata; + switch (p_notification) { + case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: + case RendererStorage::DEPENDENCY_CHANGED_AABB: { + singleton->_instance_queue_update(instance, true, false); + + } break; + case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: { + singleton->_instance_queue_update(instance, false, true); + } break; + case RendererStorage::DEPENDENCY_CHANGED_MESH: + case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: + case RendererStorage::DEPENDENCY_CHANGED_DECAL: + case RendererStorage::DEPENDENCY_CHANGED_LIGHT: + case RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE: { + singleton->_instance_queue_update(instance, true, true); + } break; + case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: + case RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES: { + //ignored + } break; + } + } + + static void dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *tracker) { + Instance *instance = (Instance *)tracker->userdata; + + if (p_dependency == instance->base) { + singleton->instance_set_base(instance->self, RID()); + } else if (p_dependency == instance->skeleton) { + singleton->instance_attach_skeleton(instance->self, RID()); + } else { + singleton->_instance_queue_update(instance, false, true); + } + } + + Instance() : + scenario_item(this), + update_item(this) { + base_type = RS::INSTANCE_NONE; + cast_shadows = RS::SHADOW_CASTING_SETTING_ON; + receive_shadows = true; + visible = true; + layer_mask = 1; + baked_light = false; + dynamic_gi = false; + redraw_if_visible = false; + lightmap_slice_index = 0; + lightmap = nullptr; + lightmap_cull_index = 0; + lod_bias = 1.0; + + scenario = nullptr; + + update_aabb = false; + update_dependencies = false; + + extra_margin = 0; + + visible = true; + + lod_begin = 0; + lod_end = 0; + lod_begin_hysteresis = 0; + lod_end_hysteresis = 0; + + last_frame_pass = 0; + version = 1; + base_data = nullptr; + + custom_aabb = nullptr; + + pair_check = 0; + array_index = -1; + + dependency_tracker.userdata = this; + dependency_tracker.changed_callback = dependency_changed; + dependency_tracker.deleted_callback = dependency_deleted; + } + + ~Instance() { + if (base_data) { + memdelete(base_data); + } + if (custom_aabb) { + memdelete(custom_aabb); + } + } + }; + + SelfList<Instance>::List _instance_update_list; + void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false); + + struct InstanceGeometryData : public InstanceBaseData { + RendererSceneRender::GeometryInstance *geometry_instance = nullptr; + Set<Instance *> lights; + bool can_cast_shadows; + bool material_is_animated; + + Set<Instance *> decals; + Set<Instance *> reflection_probes; + Set<Instance *> gi_probes; + Set<Instance *> lightmap_captures; + + InstanceGeometryData() { + can_cast_shadows = true; + material_is_animated = true; + } + }; + + struct InstanceReflectionProbeData : public InstanceBaseData { + Instance *owner; + + Set<Instance *> geometries; + + RID instance; + SelfList<InstanceReflectionProbeData> update_list; + + int render_step; + + InstanceReflectionProbeData() : + update_list(this) { + render_step = -1; + } + }; + + struct InstanceDecalData : public InstanceBaseData { + Instance *owner; + RID instance; + + Set<Instance *> geometries; + + InstanceDecalData() { + } + }; + + SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list; + + struct InstanceParticlesCollisionData : public InstanceBaseData { + RID instance; + }; + + struct InstanceLightData : public InstanceBaseData { + RID instance; + uint64_t last_version; + List<Instance *>::Element *D; // directional light in scenario + + bool shadow_dirty; + + Set<Instance *> geometries; + + Instance *baked_light; + + RS::LightBakeMode bake_mode; + uint32_t max_sdfgi_cascade = 2; + + InstanceLightData() { + bake_mode = RS::LIGHT_BAKE_DISABLED; + shadow_dirty = true; + D = nullptr; + last_version = 0; + baked_light = nullptr; + } + }; + + struct InstanceGIProbeData : public InstanceBaseData { + Instance *owner; + + Set<Instance *> geometries; + Set<Instance *> dynamic_geometries; + + Set<Instance *> lights; + + struct LightCache { + RS::LightType type; + Transform transform; + Color color; + float energy; + float bake_energy; + float radius; + float attenuation; + float spot_angle; + float spot_attenuation; + bool has_shadow; + bool sky_only; + }; + + Vector<LightCache> light_cache; + Vector<RID> light_instances; + + RID probe_instance; + + bool invalid; + uint32_t base_version; + + SelfList<InstanceGIProbeData> update_element; + + InstanceGIProbeData() : + update_element(this) { + invalid = true; + base_version = 0; + } + }; + + SelfList<InstanceGIProbeData>::List gi_probe_update_list; + + struct InstanceLightmapData : public InstanceBaseData { + RID instance; + Set<Instance *> geometries; + Set<Instance *> users; + + InstanceLightmapData() { + } + }; + + uint64_t pair_pass = 1; + + struct PairInstances { + Instance *instance = nullptr; + PagedAllocator<InstancePair> *pair_allocator = nullptr; + SelfList<InstancePair>::List pairs_found; + DynamicBVH *bvh = nullptr; + DynamicBVH *bvh2 = nullptr; //some may need to cull in two + uint32_t pair_mask; + uint64_t pair_pass; + + _FORCE_INLINE_ bool operator()(void *p_data) { + Instance *p_instance = (Instance *)p_data; + if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type))) { + //test is more coarse in indexer + p_instance->pair_check = pair_pass; + InstancePair *pair = pair_allocator->alloc(); + pair->a = instance; + pair->b = p_instance; + pairs_found.add(&pair->list_a); + } + return false; + } + + void pair() { + if (bvh) { + bvh->aabb_query(instance->transformed_aabb, *this); + } + if (bvh2) { + bvh2->aabb_query(instance->transformed_aabb, *this); + } + while (instance->pairs.first()) { + InstancePair *pair = instance->pairs.first()->self(); + Instance *other_instance = instance == pair->a ? pair->b : pair->a; + if (other_instance->pair_check != pair_pass) { + //unpaired + _instance_unpair(instance, other_instance); + } else { + //kept + other_instance->pair_check = 0; // if kept, then put pair check to zero, so we can distinguish with the newly added ones + } + + pair_allocator->free(pair); + } + while (pairs_found.first()) { + InstancePair *pair = pairs_found.first()->self(); + pairs_found.remove(pairs_found.first()); + + if (pair->b->pair_check == pair_pass) { + //paired + _instance_pair(instance, pair->b); + } + pair->a->pairs.add(&pair->list_a); + pair->b->pairs.add(&pair->list_b); + } + } + }; + + Set<Instance *> heightfield_particle_colliders_update_list; + + PagedArrayPool<Instance *> instance_cull_page_pool; + PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool; + PagedArrayPool<RID> rid_cull_page_pool; + + PagedArray<Instance *> instance_cull_result; + PagedArray<Instance *> instance_shadow_cull_result; + PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances_to_shadow_render; + + struct FrustumCullResult { + PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances; + PagedArray<Instance *> lights; + PagedArray<RID> light_instances; + PagedArray<RID> lightmaps; + PagedArray<RID> reflections; + PagedArray<RID> decals; + PagedArray<RID> gi_probes; + PagedArray<RID> mesh_instances; + + struct DirectionalShadow { + PagedArray<RendererSceneRender::GeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES]; + } directional_shadows[RendererSceneRender::MAX_DIRECTIONAL_LIGHTS]; + + PagedArray<RendererSceneRender::GeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; + PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES]; + + void clear() { + geometry_instances.clear(); + lights.clear(); + light_instances.clear(); + lightmaps.clear(); + reflections.clear(); + decals.clear(); + gi_probes.clear(); + mesh_instances.clear(); + for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) { + for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) { + directional_shadows[i].cascade_geometry_instances[j].clear(); + } + } + + for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) { + sdfgi_region_geometry_instances[i].clear(); + } + + for (int i = 0; i < SDFGI_MAX_CASCADES; i++) { + sdfgi_cascade_lights[i].clear(); + } + } + + void reset() { + geometry_instances.reset(); + lights.reset(); + light_instances.reset(); + lightmaps.reset(); + reflections.reset(); + decals.reset(); + gi_probes.reset(); + mesh_instances.reset(); + for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) { + for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) { + directional_shadows[i].cascade_geometry_instances[j].reset(); + } + } + + for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) { + sdfgi_region_geometry_instances[i].reset(); + } + + for (int i = 0; i < SDFGI_MAX_CASCADES; i++) { + sdfgi_cascade_lights[i].reset(); + } + } + + void append_from(FrustumCullResult &p_cull_result) { + geometry_instances.merge_unordered(p_cull_result.geometry_instances); + lights.merge_unordered(p_cull_result.lights); + light_instances.merge_unordered(p_cull_result.light_instances); + lightmaps.merge_unordered(p_cull_result.lightmaps); + reflections.merge_unordered(p_cull_result.reflections); + decals.merge_unordered(p_cull_result.decals); + gi_probes.merge_unordered(p_cull_result.gi_probes); + mesh_instances.merge_unordered(p_cull_result.mesh_instances); + + for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) { + for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) { + directional_shadows[i].cascade_geometry_instances[j].merge_unordered(p_cull_result.directional_shadows[i].cascade_geometry_instances[j]); + } + } + + for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) { + sdfgi_region_geometry_instances[i].merge_unordered(p_cull_result.sdfgi_region_geometry_instances[i]); + } + + for (int i = 0; i < SDFGI_MAX_CASCADES; i++) { + sdfgi_cascade_lights[i].merge_unordered(p_cull_result.sdfgi_cascade_lights[i]); + } + } + + void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RendererSceneRender::GeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) { + geometry_instances.set_page_pool(p_geometry_instance_pool); + light_instances.set_page_pool(p_rid_pool); + lights.set_page_pool(p_instance_pool); + lightmaps.set_page_pool(p_rid_pool); + reflections.set_page_pool(p_rid_pool); + decals.set_page_pool(p_rid_pool); + mesh_instances.set_page_pool(p_rid_pool); + for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) { + for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) { + directional_shadows[i].cascade_geometry_instances[j].set_page_pool(p_geometry_instance_pool); + } + } + + for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) { + sdfgi_region_geometry_instances[i].set_page_pool(p_geometry_instance_pool); + } + + for (int i = 0; i < SDFGI_MAX_CASCADES; i++) { + sdfgi_cascade_lights[i].set_page_pool(p_rid_pool); + } + } + }; + + FrustumCullResult frustum_cull_result; + LocalVector<FrustumCullResult> frustum_cull_result_threads; + + uint32_t thread_cull_threshold = 200; + + RID_PtrOwner<Instance> instance_owner; + + uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecesary on clustered + + virtual RID instance_create(); + + virtual void instance_set_base(RID p_instance, RID p_base); + virtual void instance_set_scenario(RID p_instance, RID p_scenario); + virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); + virtual void instance_set_transform(RID p_instance, const Transform &p_transform); + virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); + virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); + virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material); + virtual void instance_set_visible(RID p_instance, bool p_visible); + + virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb); + + virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton); + virtual void instance_set_exterior(RID p_instance, bool p_enabled); + + virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin); + + // don't use these in a game! + virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const; + virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; + virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const; + + virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled); + virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting); + virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); + + virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin); + virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance); + virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index); + virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias); + + void _update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material); + + virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value); + virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const; + virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const; + virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const; + + _FORCE_INLINE_ void _update_instance(Instance *p_instance); + _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); + _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance); + _FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance); + void _unpair_instance(Instance *p_instance); + + void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect); + + _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_lod_threshold); + + RID _render_get_environment(RID p_camera, RID p_scenario); + + struct Cull { + struct Shadow { + RID light_instance; + struct Cascade { + Frustum frustum; + + CameraMatrix projection; + Transform transform; + real_t zfar; + real_t split; + real_t shadow_texel_size; + real_t bias_scale; + real_t range_begin; + Vector2 uv_scale; + + } cascades[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES]; //max 4 cascades + uint32_t cascade_count; + + } shadows[RendererSceneRender::MAX_DIRECTIONAL_LIGHTS]; + + uint32_t shadow_count; + + struct SDFGI { + //have arrays here because SDFGI functions expects this, plus regions can have areas + AABB region_aabb[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade + uint32_t region_cascade[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade + uint32_t region_count = 0; + + uint32_t cascade_light_index[SDFGI_MAX_CASCADES]; + uint32_t cascade_light_count = 0; + + } sdfgi; + + SpinLock lock; + + Frustum frustum; + } cull; + + struct FrustumCullData { + Cull *cull; + Scenario *scenario; + RID shadow_atlas; + Transform cam_transform; + uint32_t visible_layers; + Instance *render_reflection_probe; + }; + + void _frustum_cull_threaded(uint32_t p_thread, FrustumCullData *cull_data); + void _frustum_cull(FrustumCullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to); + + bool _render_reflection_probe_step(Instance *p_instance, int p_step); + void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows = true); + void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold); + void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas); + + void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas); + void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, float p_screen_lod_threshold, RID p_shadow_atlas); + void update_dirty_instances(); + + void render_particle_colliders(); + virtual void render_probes(); + + TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size); + + //pass to scene render + + /* ENVIRONMENT API */ + +#ifdef PASSBASE +#undef PASSBASE +#endif + +#define PASSBASE scene_render + + PASS1(directional_shadow_atlas_set_size, int) + PASS1(gi_probe_set_quality, RS::GIProbeQuality) + + /* SKY API */ + + PASS0R(RID, sky_create) + PASS2(sky_set_radiance_size, RID, int) + PASS2(sky_set_mode, RID, RS::SkyMode) + PASS2(sky_set_material, RID, RID) + PASS4R(Ref<Image>, sky_bake_panorama, RID, float, bool, const Size2i &) + + PASS0R(RID, environment_create) + + PASS1RC(bool, is_environment, RID) + + PASS2(environment_set_background, RID, RS::EnvironmentBG) + PASS2(environment_set_sky, RID, RID) + PASS2(environment_set_sky_custom_fov, RID, float) + PASS2(environment_set_sky_orientation, RID, const Basis &) + PASS2(environment_set_bg_color, RID, const Color &) + PASS2(environment_set_bg_energy, RID, float) + PASS2(environment_set_canvas_max_layer, RID, int) + PASS7(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource, const Color &) + + PASS6(environment_set_ssr, RID, bool, int, float, float, float) + PASS1(environment_set_ssr_roughness_quality, RS::EnvironmentSSRRoughnessQuality) + + PASS10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float) + PASS6(environment_set_ssao_quality, RS::EnvironmentSSAOQuality, bool, float, int, float, float) + + PASS11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float) + PASS1(environment_glow_set_use_bicubic_upscale, bool) + PASS1(environment_glow_set_use_high_quality, bool) + + PASS9(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float, bool, float, float, float, float) + + PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) + + PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) + PASS9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, RS::EnvVolumetricFogShadowFilter) + + PASS2(environment_set_volumetric_fog_volume_size, int, int) + PASS1(environment_set_volumetric_fog_filter_active, bool) + PASS1(environment_set_volumetric_fog_directional_shadow_shrink_size, int) + PASS1(environment_set_volumetric_fog_positional_shadow_shrink_size, int) + + PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, bool, bool, float, float, float) + PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount) + PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge) + + PASS1RC(RS::EnvironmentBG, environment_get_background, RID) + PASS1RC(int, environment_get_canvas_max_layer, RID) + + PASS3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &) + + PASS3(screen_space_roughness_limiter_set_active, bool, float, float) + PASS1(sub_surface_scattering_set_quality, RS::SubSurfaceScatteringQuality) + PASS2(sub_surface_scattering_set_scale, float, float) + + /* CAMERA EFFECTS */ + + PASS0R(RID, camera_effects_create) + + PASS2(camera_effects_set_dof_blur_quality, RS::DOFBlurQuality, bool) + PASS1(camera_effects_set_dof_blur_bokeh_shape, RS::DOFBokehShape) + + PASS8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) + PASS3(camera_effects_set_custom_exposure, RID, bool, float) + + PASS1(shadows_quality_set, RS::ShadowQuality) + PASS1(directional_shadow_quality_set, RS::ShadowQuality) + + PASS2(sdfgi_set_debug_probe_select, const Vector3 &, const Vector3 &) + + /* Render Buffers */ + + PASS0R(RID, render_buffers_create) + PASS7(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool) + + /* Shadow Atlas */ + PASS0R(RID, shadow_atlas_create) + PASS2(shadow_atlas_set_size, RID, int) + PASS3(shadow_atlas_set_quadrant_subdivision, RID, int, int) + + PASS1(set_debug_draw_mode, RS::ViewportDebugDraw) + + virtual void update(); + + bool free(RID p_rid); + + void set_scene_render(RendererSceneRender *p_scene_render); + + RendererSceneCull(); + virtual ~RendererSceneCull(); +}; + +#endif // VISUALSERVERSCENE_H diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp new file mode 100644 index 0000000000..f27bdc6798 --- /dev/null +++ b/servers/rendering/renderer_scene_render.cpp @@ -0,0 +1,31 @@ +/*************************************************************************/ +/* renderer_scene_render.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#include "renderer_scene_render.h" diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h new file mode 100644 index 0000000000..85353c400d --- /dev/null +++ b/servers/rendering/renderer_scene_render.h @@ -0,0 +1,230 @@ +/*************************************************************************/ +/* renderer_scene_render.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RENDERINGSERVERSCENERENDER_H +#define RENDERINGSERVERSCENERENDER_H + +#include "core/math/camera_matrix.h" +#include "core/templates/paged_array.h" +#include "servers/rendering/renderer_storage.h" + +class RendererSceneRender { +public: + enum { + MAX_DIRECTIONAL_LIGHTS = 8, + MAX_DIRECTIONAL_LIGHT_CASCADES = 4 + }; + + struct GeometryInstance { + virtual ~GeometryInstance() {} + }; + + virtual GeometryInstance *geometry_instance_create(RID p_base) = 0; + virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0; + virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0; + virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0; + virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0; + virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0; + virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0; + virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0; + virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0; + virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0; + virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0; + virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) = 0; + virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) = 0; + virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) = 0; + + virtual uint32_t geometry_instance_get_pair_mask() = 0; + virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0; + virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0; + virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0; + virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) = 0; + + virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0; + + /* SHADOW ATLAS API */ + + virtual RID + shadow_atlas_create() = 0; + virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0; + virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0; + virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0; + + virtual void directional_shadow_atlas_set_size(int p_size) = 0; + virtual int get_directional_light_shadow_size(RID p_light_intance) = 0; + virtual void set_directional_shadow_count(int p_count) = 0; + + /* SDFGI UPDATE */ + + virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0; + virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0; + virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0; + virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0; + virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const Vector<RID> &p_directional_lights, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0; + + /* SKY API */ + + virtual RID sky_create() = 0; + virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; + virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0; + virtual void sky_set_material(RID p_sky, RID p_material) = 0; + virtual Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) = 0; + + /* ENVIRONMENT API */ + + virtual RID environment_create() = 0; + + virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0; + virtual void environment_set_sky(RID p_env, RID p_sky) = 0; + virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; + virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; + virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; + virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; + virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; +#endif + + virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0; + virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; + virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; + + virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0; + + virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0; + virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0; + virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) = 0; + virtual void environment_set_volumetric_fog_positional_shadow_shrink_size(int p_shrink_size) = 0; + + virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0; + virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0; + + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0; + + 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) = 0; + + virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + + virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0; + virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0; + + virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; + + virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0; + + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; + + virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; + + virtual bool is_environment(RID p_env) const = 0; + virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0; + virtual int environment_get_canvas_max_layer(RID p_env) const = 0; + + virtual RID camera_effects_create() = 0; + + virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0; + virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0; + + virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; + virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; + + virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0; + virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0; + + virtual RID light_instance_create(RID p_light) = 0; + virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0; + virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0; + virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0; + virtual void light_instance_mark_visible(RID p_light_instance) = 0; + virtual bool light_instances_can_render_shadow_cube() const { + return true; + } + + virtual RID reflection_atlas_create() = 0; + virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0; + virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0; + + virtual RID reflection_probe_instance_create(RID p_probe) = 0; + virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0; + virtual void reflection_probe_release_atlas_index(RID p_instance) = 0; + virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0; + virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0; + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0; + virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0; + + virtual RID decal_instance_create(RID p_decal) = 0; + virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform) = 0; + + virtual RID lightmap_instance_create(RID p_lightmap) = 0; + virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) = 0; + + virtual RID gi_probe_instance_create(RID p_gi_probe) = 0; + virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0; + virtual bool gi_probe_needs_update(RID p_probe) const = 0; + virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0; + + virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0; + + virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0; + + virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0; + virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) = 0; + virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_lights) = 0; + virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0; + + virtual void set_scene_pass(uint64_t p_pass) = 0; + virtual void set_time(double p_time, double p_step) = 0; + virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; + + virtual RID render_buffers_create() = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0; + + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; + virtual bool screen_space_roughness_limiter_is_active() const = 0; + + virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0; + virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0; + + virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0; + + virtual bool free(RID p_rid) = 0; + + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0; + + virtual bool is_low_end() const = 0; + + virtual void update() = 0; + virtual ~RendererSceneRender() {} +}; + +#endif // RENDERINGSERVERSCENERENDER_H diff --git a/servers/rendering/rasterizer.cpp b/servers/rendering/renderer_storage.cpp index 32084c8a3e..a402ecc668 100644 --- a/servers/rendering/rasterizer.cpp +++ b/servers/rendering/renderer_storage.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rasterizer.cpp */ +/* renderer_storage.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,49 +28,41 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rasterizer.h" +#include "renderer_storage.h" -#include "core/os/os.h" -#include "core/string/print_string.h" +RendererStorage *RendererStorage::base_singleton = nullptr; -Rasterizer *(*Rasterizer::_create_func)() = nullptr; - -void RasterizerScene::InstanceDependency::instance_notify_changed(bool p_aabb, bool p_dependencies) { - for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { - E->key()->dependency_changed(p_aabb, p_dependencies); +void RendererStorage::Dependency::changed_notify(DependencyChangedNotification p_notification) { + for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { + if (E->key()->changed_callback) { + E->key()->changed_callback(p_notification, E->key()); + } } } -void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted) { - for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { - E->key()->dependency_deleted(p_deleted); +void RendererStorage::Dependency::deleted_notify(const RID &p_rid) { + for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { + if (E->key()->deleted_callback) { + E->key()->deleted_callback(p_rid, E->key()); + } } - for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { + for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { E->key()->dependencies.erase(this); } - instances.clear(); } -RasterizerScene::InstanceDependency::~InstanceDependency() { +RendererStorage::Dependency::~Dependency() { #ifdef DEBUG_ENABLED if (instances.size()) { WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing."); - for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { + for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) { E->key()->dependencies.erase(this); } } #endif } -Rasterizer *Rasterizer::create() { - return _create_func(); -} - -RasterizerCanvas *RasterizerCanvas::singleton = nullptr; - -RasterizerStorage *RasterizerStorage::base_singleton = nullptr; - -RasterizerStorage::RasterizerStorage() { +RendererStorage::RendererStorage() { base_singleton = this; } diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h new file mode 100644 index 0000000000..64c23c7803 --- /dev/null +++ b/servers/rendering/renderer_storage.h @@ -0,0 +1,623 @@ +/*************************************************************************/ +/* renderer_storage.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RENDERINGSERVERSTORAGE_H +#define RENDERINGSERVERSTORAGE_H + +#include "servers/rendering_server.h" + +class RendererStorage { + Color default_clear_color; + +public: + enum DependencyChangedNotification { + DEPENDENCY_CHANGED_AABB, + DEPENDENCY_CHANGED_MATERIAL, + DEPENDENCY_CHANGED_MESH, + DEPENDENCY_CHANGED_MULTIMESH, + DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES, + DEPENDENCY_CHANGED_DECAL, + DEPENDENCY_CHANGED_SKELETON_DATA, + DEPENDENCY_CHANGED_SKELETON_BONES, + DEPENDENCY_CHANGED_LIGHT, + DEPENDENCY_CHANGED_REFLECTION_PROBE, + }; + + struct DependencyTracker; + +protected: + struct Dependency { + void changed_notify(DependencyChangedNotification p_notification); + void deleted_notify(const RID &p_rid); + + ~Dependency(); + + private: + friend struct DependencyTracker; + Map<DependencyTracker *, uint32_t> instances; + }; + +public: + struct DependencyTracker { + void *userdata = nullptr; + typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *); + typedef void (*DeletedCallback)(const RID &, DependencyTracker *); + + ChangedCallback changed_callback = nullptr; + DeletedCallback deleted_callback = nullptr; + + void update_begin() { // call before updating dependencies + instance_version++; + } + + void update_dependency(Dependency *p_dependency) { //called internally, can't be used directly, use update functions in Storage + dependencies.insert(p_dependency); + p_dependency->instances[this] = instance_version; + } + + void update_end() { //call after updating dependencies + List<Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *>> to_clean_up; + for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { + Dependency *dep = E->get(); + Map<DependencyTracker *, uint32_t>::Element *F = dep->instances.find(this); + ERR_CONTINUE(!F); + if (F->get() != instance_version) { + Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *> p; + p.first = dep; + p.second = F; + to_clean_up.push_back(p); + } + } + + while (to_clean_up.size()) { + to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second); + to_clean_up.pop_front(); + } + } + + void clear() { // clear all dependencies + for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) { + Dependency *dep = E->get(); + dep->instances.erase(this); + } + dependencies.clear(); + } + + ~DependencyTracker() { clear(); } + + private: + friend struct Dependency; + uint32_t instance_version = 0; + Set<Dependency *> dependencies; + }; + + /* TEXTURE API */ + + virtual RID texture_2d_create(const Ref<Image> &p_image) = 0; + virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; + virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; + virtual RID texture_proxy_create(RID p_base) = 0; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming + virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; + + //these two APIs can be used together or in combination with the others. + virtual RID texture_2d_placeholder_create() = 0; + virtual RID texture_2d_layered_placeholder_create(RenderingServer::TextureLayeredType p_layered_type) = 0; + virtual RID texture_3d_placeholder_create() = 0; + + virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; + virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; + + virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; + + virtual void texture_set_path(RID p_texture, const String &p_path) = 0; + virtual String texture_get_path(RID p_texture) const = 0; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; + + virtual void texture_debug_usage(List<RS::TextureInfo> *r_info) = 0; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; + + virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; + + virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; + virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; + + /* CANVAS TEXTURE API */ + + virtual RID canvas_texture_create() = 0; + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; + + /* SHADER API */ + + virtual RID shader_create() = 0; + + virtual void shader_set_code(RID p_shader, const String &p_code) = 0; + virtual String shader_get_code(RID p_shader) const = 0; + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; + virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; + + virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0; + + /* COMMON MATERIAL API */ + + virtual RID material_create() = 0; + + virtual void material_set_render_priority(RID p_material, int priority) = 0; + virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; + virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; + + virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; + + virtual bool material_is_animated(RID p_material) = 0; + virtual bool material_casts_shadows(RID p_material) = 0; + + struct InstanceShaderParam { + PropertyInfo info; + int index; + Variant default_value; + }; + + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; + + virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0; + + /* MESH API */ + + virtual RID mesh_create() = 0; + + virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0; + + /// Returns stride + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0; + + virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0; + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; + + virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; + + virtual int mesh_get_surface_count(RID p_mesh) const = 0; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; + virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; + + virtual void mesh_clear(RID p_mesh) = 0; + + virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0; + + /* MESH INSTANCE */ + + virtual RID mesh_instance_create(RID p_base) = 0; + virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0; + virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0; + virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0; + virtual void update_mesh_instances() = 0; + + /* MULTIMESH API */ + + virtual RID multimesh_create() = 0; + + virtual void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; + + virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; + + virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; + + virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; + + virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0; + virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0; + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; + virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; + + virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; + + /* IMMEDIATE API */ + + virtual RID immediate_create() = 0; + virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0; + virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0; + virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0; + virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0; + virtual void immediate_color(RID p_immediate, const Color &p_color) = 0; + virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0; + virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0; + virtual void immediate_end(RID p_immediate) = 0; + virtual void immediate_clear(RID p_immediate) = 0; + virtual void immediate_set_material(RID p_immediate, RID p_material) = 0; + virtual RID immediate_get_material(RID p_immediate) const = 0; + virtual AABB immediate_get_aabb(RID p_immediate) const = 0; + + /* SKELETON API */ + + virtual RID skeleton_create() = 0; + virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; + virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0; + virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; + + /* Light API */ + + virtual RID light_create(RS::LightType p_type) = 0; + + RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); } + RID omni_light_create() { return light_create(RS::LIGHT_OMNI); } + RID spot_light_create() { return light_create(RS::LIGHT_SPOT); } + + virtual void light_set_color(RID p_light, const Color &p_color) = 0; + virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0; + virtual void light_set_shadow(RID p_light, bool p_enabled) = 0; + virtual void light_set_shadow_color(RID p_light, const Color &p_color) = 0; + virtual void light_set_projector(RID p_light, RID p_texture) = 0; + virtual void light_set_negative(RID p_light, bool p_enable) = 0; + virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; + virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; + virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0; + virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0; + + virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0; + + virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0; + virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; + virtual bool light_directional_get_blend_splits(RID p_light) const = 0; + virtual void light_directional_set_sky_only(RID p_light, bool p_sky_only) = 0; + virtual bool light_directional_is_sky_only(RID p_light) const = 0; + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0; + virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0; + + virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0; + virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0; + + virtual bool light_has_shadow(RID p_light) const = 0; + + virtual RS::LightType light_get_type(RID p_light) const = 0; + virtual AABB light_get_aabb(RID p_light) const = 0; + virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0; + virtual Color light_get_color(RID p_light) = 0; + virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0; + virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0; + virtual uint64_t light_get_version(RID p_light) const = 0; + + /* PROBE API */ + + virtual RID reflection_probe_create() = 0; + + virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0; + virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0; + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0; + virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0; + virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0; + virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0; + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; + virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0; + virtual void reflection_probe_set_lod_threshold(RID p_probe, float p_ratio) = 0; + + virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0; + virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0; + virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0; + virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0; + virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0; + virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0; + virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0; + virtual float reflection_probe_get_lod_threshold(RID p_probe) const = 0; + + virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; + virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0; + + /* DECAL API */ + + virtual RID decal_create() = 0; + virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0; + virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0; + virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0; + virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0; + virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0; + virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0; + virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0; + virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0; + virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0; + + virtual AABB decal_get_aabb(RID p_decal) const = 0; + + /* GI PROBE API */ + + virtual RID gi_probe_create() = 0; + + virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0; + + virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0; + virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0; + virtual Vector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const = 0; + virtual Vector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const = 0; + virtual Vector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const = 0; + + virtual Vector<int> gi_probe_get_level_counts(RID p_gi_probe) const = 0; + virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0; + virtual float gi_probe_get_energy(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0; + virtual float gi_probe_get_ao(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0; + virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0; + virtual float gi_probe_get_bias(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0; + virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0; + virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; + virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; + + virtual uint32_t gi_probe_get_version(RID p_probe) = 0; + + /* LIGHTMAP CAPTURE */ + + virtual RID lightmap_create() = 0; + + virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0; + virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0; + virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0; + virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0; + virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0; + virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0; + virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0; + virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0; + virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0; + virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0; + virtual bool lightmap_is_interior(RID p_lightmap) const = 0; + virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0; + virtual float lightmap_get_probe_capture_update_speed() const = 0; + + /* PARTICLES */ + + virtual RID particles_create() = 0; + + virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; + virtual bool particles_get_emitting(RID p_particles) = 0; + + virtual void particles_set_amount(RID p_particles, int p_amount) = 0; + virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0; + virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; + virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0; + virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0; + virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0; + virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0; + virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0; + virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; + virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; + virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; + virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; + virtual void particles_set_collision_base_size(RID p_particles, float p_size) = 0; + virtual void particles_restart(RID p_particles) = 0; + virtual void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0; + virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0; + + virtual bool particles_is_inactive(RID p_particles) const = 0; + + virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0; + + virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; + virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; + + virtual void particles_request_process(RID p_particles) = 0; + virtual AABB particles_get_current_aabb(RID p_particles) = 0; + virtual AABB particles_get_aabb(RID p_particles) const = 0; + + virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; + + virtual int particles_get_draw_passes(RID p_particles) const = 0; + virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0; + + virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis) = 0; + + virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0; + virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0; + + virtual void update_particles() = 0; + + /* PARTICLES COLLISION */ + + virtual RID particles_collision_create() = 0; + virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0; + virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0; + virtual void particles_collision_set_sphere_radius(RID p_particles_collision, float p_radius) = 0; //for spheres + virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres + virtual void particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) = 0; + virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, float p_directionality) = 0; + virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, float p_curve) = 0; + virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic + virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field + virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field + virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0; + virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0; + virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0; + + //used from 2D and 3D + virtual RID particles_collision_instance_create(RID p_collision) = 0; + virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) = 0; + virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0; + + /* GLOBAL VARIABLES */ + + virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0; + virtual void global_variable_remove(const StringName &p_name) = 0; + virtual Vector<StringName> global_variable_get_list() const = 0; + + virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0; + virtual Variant global_variable_get(const StringName &p_name) const = 0; + virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0; + + virtual void global_variables_load_settings(bool p_load_textures = true) = 0; + virtual void global_variables_clear() = 0; + + virtual int32_t global_variables_instance_allocate(RID p_instance) = 0; + virtual void global_variables_instance_free(RID p_instance) = 0; + virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; + + /* RENDER TARGET */ + + enum RenderTargetFlags { + RENDER_TARGET_TRANSPARENT, + RENDER_TARGET_DIRECT_TO_SCREEN, + RENDER_TARGET_FLAG_MAX + }; + + virtual RID render_target_create() = 0; + virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; + virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0; + virtual RID render_target_get_texture(RID p_render_target) = 0; + virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0; + virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0; + virtual bool render_target_was_used(RID p_render_target) = 0; + virtual void render_target_set_as_unused(RID p_render_target) = 0; + + virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0; + virtual bool render_target_is_clear_requested(RID p_render_target) = 0; + virtual Color render_target_get_clear_request_color(RID p_render_target) = 0; + virtual void render_target_disable_clear_request(RID p_render_target) = 0; + virtual void render_target_do_clear_request(RID p_render_target) = 0; + + virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0; + virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0; + + virtual RS::InstanceType get_base_type(RID p_rid) const = 0; + virtual bool free(RID p_rid) = 0; + + virtual bool has_os_feature(const String &p_feature) const = 0; + + virtual void update_dirty_resources() = 0; + + virtual void set_debug_generate_wireframes(bool p_generate) = 0; + + virtual void render_info_begin_capture() = 0; + virtual void render_info_end_capture() = 0; + virtual int get_captured_render_info(RS::RenderInfo p_info) = 0; + + virtual int get_render_info(RS::RenderInfo p_info) = 0; + virtual String get_video_adapter_name() const = 0; + virtual String get_video_adapter_vendor() const = 0; + + static RendererStorage *base_singleton; + + void set_default_clear_color(const Color &p_color) { + default_clear_color = p_color; + } + + Color get_default_clear_color() const { + return default_clear_color; + } +#define TIMESTAMP_BEGIN() \ + { \ + if (RSG::storage->capturing_timestamps) \ + RSG::storage->capture_timestamps_begin(); \ + } + +#define RENDER_TIMESTAMP(m_text) \ + { \ + if (RSG::storage->capturing_timestamps) \ + RSG::storage->capture_timestamp(m_text); \ + } + + bool capturing_timestamps = false; + + virtual void capture_timestamps_begin() = 0; + virtual void capture_timestamp(const String &p_name) = 0; + virtual uint32_t get_captured_timestamps_count() const = 0; + virtual uint64_t get_captured_timestamps_frame() const = 0; + virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0; + virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0; + virtual String get_captured_timestamp_name(uint32_t p_index) const = 0; + + RendererStorage(); + virtual ~RendererStorage() {} +}; + +#endif // RENDERINGSERVERSTORAGE_H diff --git a/servers/rendering/renderer_thread_pool.cpp b/servers/rendering/renderer_thread_pool.cpp new file mode 100644 index 0000000000..98050dd508 --- /dev/null +++ b/servers/rendering/renderer_thread_pool.cpp @@ -0,0 +1,42 @@ +/*************************************************************************/ +/* renderer_thread_pool.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#include "renderer_thread_pool.h" + +RendererThreadPool *RendererThreadPool::singleton = nullptr; + +RendererThreadPool::RendererThreadPool() { + singleton = this; + thread_work_pool.init(); +} + +RendererThreadPool::~RendererThreadPool() { + thread_work_pool.finish(); +} diff --git a/servers/rendering/renderer_thread_pool.h b/servers/rendering/renderer_thread_pool.h new file mode 100644 index 0000000000..ae25415a0d --- /dev/null +++ b/servers/rendering/renderer_thread_pool.h @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* renderer_thread_pool.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 RENDERERTHREADPOOL_H +#define RENDERERTHREADPOOL_H + +#include "core/templates/thread_work_pool.h" + +class RendererThreadPool { +public: + ThreadWorkPool thread_work_pool; + + static RendererThreadPool *singleton; + RendererThreadPool(); + ~RendererThreadPool(); +}; + +#endif // RENDERERTHREADPOOL_H diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/renderer_viewport.cpp index c048aa381f..9956e4050b 100644 --- a/servers/rendering/rendering_server_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rendering_server_viewport.cpp */ +/* renderer_viewport.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rendering_server_viewport.h" +#include "renderer_viewport.h" #include "core/config/project_settings.h" -#include "rendering_server_canvas.h" +#include "renderer_canvas_cull.h" +#include "renderer_scene_cull.h" #include "rendering_server_globals.h" -#include "rendering_server_scene.h" -static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_viewport, RenderingServerCanvas::Canvas *p_canvas, RenderingServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) { +static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport, RendererCanvasCull::Canvas *p_canvas, RendererViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) { Transform2D xf = p_viewport->global_transform; float scale = 1.0; @@ -71,7 +71,7 @@ static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_vi return xf; } -void RenderingServerViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye) { +void RendererViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p_eye) { RENDER_TIMESTAMP(">Begin Rendering 3D Scene"); Ref<XRInterface> xr_interface; @@ -79,15 +79,16 @@ void RenderingServerViewport::_draw_3d(Viewport *p_viewport, XRInterface::Eyes p xr_interface = XRServer::get_singleton()->get_primary_interface(); } + float screen_lod_threshold = p_viewport->lod_threshold / float(p_viewport->size.width); if (p_viewport->use_xr && xr_interface.is_valid()) { - RSG::scene->render_camera(p_viewport->render_buffers, xr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + RSG::scene->render_camera(p_viewport->render_buffers, xr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas); } else { - RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, screen_lod_threshold, p_viewport->shadow_atlas); } RENDER_TIMESTAMP("<End Rendering 3D Scene"); } -void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye) { +void RendererViewport::_draw_viewport(Viewport *p_viewport, XRInterface::Eyes p_eye) { if (p_viewport->measure_render_time) { String rt_id = "vp_begin_" + itos(p_viewport->self.get_id()); RSG::storage->capture_timestamp(rt_id); @@ -101,17 +102,15 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: Color bgcolor = RSG::storage->get_default_clear_color(); - if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->scenario_owner.owns(p_viewport->scenario)) { - RenderingServerScene::Scenario *scenario = RSG::scene->scenario_owner.getornull(p_viewport->scenario); - ERR_FAIL_COND(!scenario); - if (RSG::scene_render->is_environment(scenario->environment)) { - scenario_draw_canvas_bg = RSG::scene_render->environment_get_background(scenario->environment) == RS::ENV_BG_CANVAS; - - scenario_canvas_max_layer = RSG::scene_render->environment_get_canvas_max_layer(scenario->environment); + if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) { + RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario); + if (RSG::scene->is_environment(environment)) { + scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS; + scenario_canvas_max_layer = RSG::scene->environment_get_canvas_max_layer(environment); } } - bool can_draw_3d = RSG::scene->camera_owner.owns(p_viewport->camera); + bool can_draw_3d = RSG::scene->is_camera(p_viewport->camera); if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) { if (p_viewport->transparent_bg) { @@ -124,8 +123,8 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) { //wants to draw 3D but there is no render buffer, create - p_viewport->render_buffers = RSG::scene_render->render_buffers_create(); - RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding); + p_viewport->render_buffers = RSG::scene->render_buffers_create(); + RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding); } RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor); @@ -140,25 +139,25 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map; Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); - RasterizerCanvas::Light *lights = nullptr; - RasterizerCanvas::Light *lights_with_shadow = nullptr; + RendererCanvasRender::Light *lights = nullptr; + RendererCanvasRender::Light *lights_with_shadow = nullptr; - RasterizerCanvas::Light *directional_lights = nullptr; - RasterizerCanvas::Light *directional_lights_with_shadow = nullptr; + RendererCanvasRender::Light *directional_lights = nullptr; + RendererCanvasRender::Light *directional_lights_with_shadow = nullptr; if (p_viewport->sdf_active) { //process SDF Rect2 sdf_rect = RSG::storage->render_target_get_sdf_rect(p_viewport->render_target); - RasterizerCanvas::LightOccluderInstance *occluders = nullptr; + RendererCanvasRender::LightOccluderInstance *occluders = nullptr; //make list of occluders for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { - RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas); + RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get().canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); - for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -184,14 +183,14 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: RENDER_TIMESTAMP("Cull Canvas Lights"); for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { - RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas); + RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get().canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); //find lights in canvas - for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { - RasterizerCanvas::Light *cl = F->get(); + for (Set<RendererCanvasRender::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) { + RendererCanvasRender::Light *cl = F->get(); if (cl->enabled && cl->texture.is_valid()) { //not super efficient.. Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture); @@ -228,8 +227,8 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: } } - for (Set<RasterizerCanvas::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) { - RasterizerCanvas::Light *cl = F->get(); + for (Set<RendererCanvasRender::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) { + RendererCanvasRender::Light *cl = F->get(); if (cl->enabled) { cl->filter_next_ptr = directional_lights; directional_lights = cl; @@ -254,17 +253,17 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: if (lights_with_shadow) { //update shadows if any - RasterizerCanvas::LightOccluderInstance *occluders = nullptr; + RendererCanvasRender::LightOccluderInstance *occluders = nullptr; RENDER_TIMESTAMP(">Render 2D Shadows"); RENDER_TIMESTAMP("Cull Occluders"); //make list of occluders for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { - RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas); + RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get().canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); - for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -277,7 +276,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: } //update the light shadowmaps with them - RasterizerCanvas::Light *light = lights_with_shadow; + RendererCanvasRender::Light *light = lights_with_shadow; while (light) { RENDER_TIMESTAMP("Render Shadow"); @@ -290,7 +289,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: if (directional_lights_with_shadow) { //update shadows if any - RasterizerCanvas::Light *light = directional_lights_with_shadow; + RendererCanvasRender::Light *light = directional_lights_with_shadow; while (light) { Vector2 light_dir = -light->xform_cache.elements[1].normalized(); // Y is light direction float cull_distance = light->directional_distance; @@ -335,17 +334,17 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: Vector2 xf_points[6]; - RasterizerCanvas::LightOccluderInstance *occluders = nullptr; + RendererCanvasRender::LightOccluderInstance *occluders = nullptr; RENDER_TIMESTAMP(">Render Directional 2D Shadows"); //make list of occluders int occ_cullded = 0; for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { - RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas); + RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get().canvas); Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); - for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + for (Set<RendererCanvasRender::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { if (!F->get()->enabled) { continue; } @@ -381,14 +380,14 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: } for (Map<Viewport::CanvasKey, Viewport::CanvasData *>::Element *E = canvas_map.front(); E; E = E->next()) { - RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get()->canvas); + RendererCanvasCull::Canvas *canvas = static_cast<RendererCanvasCull::Canvas *>(E->get()->canvas); Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size); - RasterizerCanvas::Light *canvas_lights = nullptr; - RasterizerCanvas::Light *canvas_directional_lights = nullptr; + RendererCanvasRender::Light *canvas_lights = nullptr; + RendererCanvasRender::Light *canvas_directional_lights = nullptr; - RasterizerCanvas::Light *ptr = lights; + RendererCanvasRender::Light *ptr = lights; while (ptr) { if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) { ptr->next_ptr = canvas_lights; @@ -444,7 +443,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: } } -void RenderingServerViewport::draw_viewports() { +void RendererViewport::draw_viewports() { timestamp_vp_map.clear(); // get our xr interface in case we need it @@ -464,7 +463,7 @@ void RenderingServerViewport::draw_viewports() { //sort viewports active_viewports.sort_custom<ViewportSort>(); - Map<DisplayServer::WindowID, Vector<Rasterizer::BlitToScreen>> blit_to_screen_list; + Map<DisplayServer::WindowID, Vector<RendererCompositor::BlitToScreen>> blit_to_screen_list; //draw viewports RENDER_TIMESTAMP(">Render Viewports"); @@ -559,7 +558,7 @@ void RenderingServerViewport::draw_viewports() { { RSG::storage->render_target_set_external_texture(vp->render_target, 0); - RSG::scene_render->set_debug_draw_mode(vp->debug_draw); + RSG::scene->set_debug_draw_mode(vp->debug_draw); RSG::storage->render_info_begin_capture(); // render standard mono camera @@ -575,7 +574,7 @@ void RenderingServerViewport::draw_viewports() { if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !RSG::rasterizer->is_low_end())) { //copy to screen if set as such - Rasterizer::BlitToScreen blit; + RendererCompositor::BlitToScreen blit; blit.render_target = vp->render_target; if (vp->viewport_to_screen_rect != Rect2()) { blit.rect = vp->viewport_to_screen_rect; @@ -585,7 +584,7 @@ void RenderingServerViewport::draw_viewports() { } if (!blit_to_screen_list.has(vp->viewport_to_screen)) { - blit_to_screen_list[vp->viewport_to_screen] = Vector<Rasterizer::BlitToScreen>(); + blit_to_screen_list[vp->viewport_to_screen] = Vector<RendererCompositor::BlitToScreen>(); } blit_to_screen_list[vp->viewport_to_screen].push_back(blit); @@ -598,18 +597,18 @@ void RenderingServerViewport::draw_viewports() { RENDER_TIMESTAMP("<Rendering Viewport " + itos(i)); } - RSG::scene_render->set_debug_draw_mode(RS::VIEWPORT_DEBUG_DRAW_DISABLED); + RSG::scene->set_debug_draw_mode(RS::VIEWPORT_DEBUG_DRAW_DISABLED); RENDER_TIMESTAMP("<Render Viewports"); //this needs to be called to make screen swapping more efficient RSG::rasterizer->prepare_for_blitting_render_targets(); - for (Map<int, Vector<Rasterizer::BlitToScreen>>::Element *E = blit_to_screen_list.front(); E; E = E->next()) { + for (Map<int, Vector<RendererCompositor::BlitToScreen>>::Element *E = blit_to_screen_list.front(); E; E = E->next()) { RSG::rasterizer->blit_render_targets_to_screen(E->key(), E->get().ptr(), E->get().size()); } } -RID RenderingServerViewport::viewport_create() { +RID RendererViewport::viewport_create() { Viewport *viewport = memnew(Viewport); RID rid = viewport_owner.make_rid(viewport); @@ -618,20 +617,20 @@ RID RenderingServerViewport::viewport_create() { viewport->hide_scenario = false; viewport->hide_canvas = false; viewport->render_target = RSG::storage->render_target_create(); - viewport->shadow_atlas = RSG::scene_render->shadow_atlas_create(); + viewport->shadow_atlas = RSG::scene->shadow_atlas_create(); viewport->viewport_render_direct_to_screen = false; return rid; } -void RenderingServerViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) { +void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->use_xr = p_use_xr; } -void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) { +void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) { ERR_FAIL_COND(p_width < 0 && p_height < 0); Viewport *viewport = viewport_owner.getornull(p_viewport); @@ -641,15 +640,15 @@ void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height); if (viewport->render_buffers.is_valid()) { if (p_width == 0 || p_height == 0) { - RSG::scene_render->free(viewport->render_buffers); + RSG::scene->free(viewport->render_buffers); viewport->render_buffers = RID(); } else { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding); + RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding); } } } -void RenderingServerViewport::viewport_set_active(RID p_viewport, bool p_active) { +void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -661,21 +660,21 @@ void RenderingServerViewport::viewport_set_active(RID p_viewport, bool p_active) } } -void RenderingServerViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) { +void RendererViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->parent = p_parent_viewport; } -void RenderingServerViewport::viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode) { +void RendererViewport::viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->clear_mode = p_clear_mode; } -void RenderingServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, DisplayServer::WindowID p_screen) { +void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, DisplayServer::WindowID p_screen) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -701,7 +700,7 @@ void RenderingServerViewport::viewport_attach_to_screen(RID p_viewport, const Re } } -void RenderingServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) { +void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -715,7 +714,7 @@ void RenderingServerViewport::viewport_set_render_direct_to_screen(RID p_viewpor RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); } - RSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable); + RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable); viewport->viewport_render_direct_to_screen = p_enable; // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation @@ -725,61 +724,61 @@ void RenderingServerViewport::viewport_set_render_direct_to_screen(RID p_viewpor } } -void RenderingServerViewport::viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode) { +void RendererViewport::viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->update_mode = p_mode; } -RID RenderingServerViewport::viewport_get_texture(RID p_viewport) const { +RID RendererViewport::viewport_get_texture(RID p_viewport) const { const Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND_V(!viewport, RID()); return RSG::storage->render_target_get_texture(viewport->render_target); } -void RenderingServerViewport::viewport_set_hide_scenario(RID p_viewport, bool p_hide) { +void RendererViewport::viewport_set_hide_scenario(RID p_viewport, bool p_hide) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->hide_scenario = p_hide; } -void RenderingServerViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) { +void RendererViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->hide_canvas = p_hide; } -void RenderingServerViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) { +void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->disable_environment = p_disable; } -void RenderingServerViewport::viewport_attach_camera(RID p_viewport, RID p_camera) { +void RendererViewport::viewport_attach_camera(RID p_viewport, RID p_camera) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->camera = p_camera; } -void RenderingServerViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) { +void RendererViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->scenario = p_scenario; } -void RenderingServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) { +void RendererViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); ERR_FAIL_COND(viewport->canvas_map.has(p_canvas)); - RenderingServerCanvas::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas); + RendererCanvasCull::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas); ERR_FAIL_COND(!canvas); canvas->viewports.insert(p_viewport); @@ -789,18 +788,18 @@ void RenderingServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canva viewport->canvas_map[p_canvas].canvas = canvas; } -void RenderingServerViewport::viewport_remove_canvas(RID p_viewport, RID p_canvas) { +void RendererViewport::viewport_remove_canvas(RID p_viewport, RID p_canvas) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); - RenderingServerCanvas::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas); + RendererCanvasCull::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas); ERR_FAIL_COND(!canvas); viewport->canvas_map.erase(p_canvas); canvas->viewports.erase(p_viewport); } -void RenderingServerViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) { +void RendererViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -808,22 +807,22 @@ void RenderingServerViewport::viewport_set_canvas_transform(RID p_viewport, RID viewport->canvas_map[p_canvas].transform = p_offset; } -void RenderingServerViewport::viewport_set_transparent_background(RID p_viewport, bool p_enabled) { +void RendererViewport::viewport_set_transparent_background(RID p_viewport, bool p_enabled) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); - RSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_TRANSPARENT, p_enabled); + RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_TRANSPARENT, p_enabled); viewport->transparent_bg = p_enabled; } -void RenderingServerViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) { +void RendererViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->global_transform = p_transform; } -void RenderingServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) { +void RendererViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -832,23 +831,23 @@ void RenderingServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p viewport->canvas_map[p_canvas].sublayer = p_sublayer; } -void RenderingServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) { +void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->shadow_atlas_size = p_size; - RSG::scene_render->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size); + RSG::scene->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size); } -void RenderingServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) { +void RendererViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); - RSG::scene_render->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv); + RSG::scene->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv); } -void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) { +void RendererViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -857,11 +856,11 @@ void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA } viewport->msaa = p_msaa; if (viewport->render_buffers.is_valid()) { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding); + RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding); } } -void RenderingServerViewport::viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode) { +void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -870,11 +869,11 @@ void RenderingServerViewport::viewport_set_screen_space_aa(RID p_viewport, RS::V } viewport->screen_space_aa = p_mode; if (viewport->render_buffers.is_valid()) { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding); + RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding); } } -void RenderingServerViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) { +void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -883,11 +882,18 @@ void RenderingServerViewport::viewport_set_use_debanding(RID p_viewport, bool p_ } viewport->use_debanding = p_use_debanding; if (viewport->render_buffers.is_valid()) { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding); + RSG::scene->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding); } } -int RenderingServerViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info) { +void RendererViewport::viewport_set_lod_threshold(RID p_viewport, float p_pixels) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->lod_threshold = p_pixels; +} + +int RendererViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info) { ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1); Viewport *viewport = viewport_owner.getornull(p_viewport); @@ -898,54 +904,54 @@ int RenderingServerViewport::viewport_get_render_info(RID p_viewport, RS::Viewpo return viewport->render_info[p_info]; } -void RenderingServerViewport::viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw) { +void RendererViewport::viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->debug_draw = p_draw; } -void RenderingServerViewport::viewport_set_measure_render_time(RID p_viewport, bool p_enable) { +void RendererViewport::viewport_set_measure_render_time(RID p_viewport, bool p_enable) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->measure_render_time = p_enable; } -float RenderingServerViewport::viewport_get_measured_render_time_cpu(RID p_viewport) const { +float RendererViewport::viewport_get_measured_render_time_cpu(RID p_viewport) const { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND_V(!viewport, 0); return double(viewport->time_cpu_end - viewport->time_cpu_begin) / 1000.0; } -float RenderingServerViewport::viewport_get_measured_render_time_gpu(RID p_viewport) const { +float RendererViewport::viewport_get_measured_render_time_gpu(RID p_viewport) const { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND_V(!viewport, 0); return double((viewport->time_gpu_end - viewport->time_gpu_begin) / 1000) / 1000.0; } -void RenderingServerViewport::viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled) { +void RendererViewport::viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->snap_2d_transforms_to_pixel = p_enabled; } -void RenderingServerViewport::viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled) { +void RendererViewport::viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->snap_2d_vertices_to_pixel = p_enabled; } -void RenderingServerViewport::viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter) { +void RendererViewport::viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter) { ERR_FAIL_COND_MSG(p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, "Viewport does not accept DEFAULT as texture filter (it's the topmost choice already).)"); Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); viewport->texture_filter = p_filter; } -void RenderingServerViewport::viewport_set_default_canvas_item_texture_repeat(RID p_viewport, RS::CanvasItemTextureRepeat p_repeat) { +void RendererViewport::viewport_set_default_canvas_item_texture_repeat(RID p_viewport, RS::CanvasItemTextureRepeat p_repeat) { ERR_FAIL_COND_MSG(p_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, "Viewport does not accept DEFAULT as texture repeat (it's the topmost choice already).)"); Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); @@ -953,21 +959,21 @@ void RenderingServerViewport::viewport_set_default_canvas_item_texture_repeat(RI viewport->texture_repeat = p_repeat; } -void RenderingServerViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) { +void RendererViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) { Viewport *viewport = viewport_owner.getornull(p_viewport); ERR_FAIL_COND(!viewport); RSG::storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale); } -bool RenderingServerViewport::free(RID p_rid) { +bool RendererViewport::free(RID p_rid) { if (viewport_owner.owns(p_rid)) { Viewport *viewport = viewport_owner.getornull(p_rid); RSG::storage->free(viewport->render_target); - RSG::scene_render->free(viewport->shadow_atlas); + RSG::scene->free(viewport->shadow_atlas); if (viewport->render_buffers.is_valid()) { - RSG::scene_render->free(viewport->render_buffers); + RSG::scene->free(viewport->render_buffers); } while (viewport->canvas_map.front()) { @@ -986,7 +992,7 @@ bool RenderingServerViewport::free(RID p_rid) { return false; } -void RenderingServerViewport::handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time) { +void RendererViewport::handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time) { RID *vp = timestamp_vp_map.getptr(p_timestamp); if (!vp) { return; @@ -1008,9 +1014,9 @@ void RenderingServerViewport::handle_timestamp(String p_timestamp, uint64_t p_cp } } -void RenderingServerViewport::set_default_clear_color(const Color &p_color) { +void RendererViewport::set_default_clear_color(const Color &p_color) { RSG::storage->set_default_clear_color(p_color); } -RenderingServerViewport::RenderingServerViewport() { +RendererViewport::RendererViewport() { } diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/renderer_viewport.h index ba55b2e66e..c3ff52a836 100644 --- a/servers/rendering/rendering_server_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rendering_server_viewport.h */ +/* renderer_viewport.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -33,11 +33,11 @@ #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" -#include "rasterizer.h" +#include "renderer_compositor.h" #include "servers/rendering_server.h" #include "servers/xr/xr_interface.h" -class RenderingServerViewport { +class RendererViewport { public: struct CanvasBase { }; @@ -84,6 +84,8 @@ public: bool sdf_active; + float lod_threshold = 1.0; + uint64_t last_pass = 0; int render_info[RS::VIEWPORT_RENDER_INFO_MAX]; @@ -222,6 +224,8 @@ public: void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode); void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding); + void viewport_set_lod_threshold(RID p_viewport, float p_pixels); + virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info); virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw); @@ -244,8 +248,8 @@ public: bool free(RID p_rid); - RenderingServerViewport(); - virtual ~RenderingServerViewport() {} + RendererViewport(); + virtual ~RendererViewport() {} }; #endif // VISUALSERVERVIEWPORT_H diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 1259b161bd..73c86a0a1d 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -68,7 +68,7 @@ RID RenderingDevice::_texture_create(const Ref<RDTextureFormat> &p_format, const Vector<Vector<uint8_t>> data; for (int i = 0; i < p_data.size(); i++) { Vector<uint8_t> byte_slice = p_data[i]; - ERR_FAIL_COND_V(byte_slice.empty(), RID()); + ERR_FAIL_COND_V(byte_slice.is_empty(), RID()); data.push_back(byte_slice); } return texture_create(p_format->base, p_view->base, data); @@ -154,7 +154,7 @@ RID RenderingDevice::shader_create_from_bytecode(const Ref<RDShaderBytecode> &p_ String error = p_bytecode->get_stage_compile_error(stage); ERR_FAIL_COND_V_MSG(error != String(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode."); sd.spir_v = p_bytecode->get_stage_bytecode(stage); - if (sd.spir_v.empty()) { + if (sd.spir_v.is_empty()) { continue; } stage_data.push_back(sd); @@ -270,7 +270,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create); - ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector<uint8_t>())); + ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "use_as_storage"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create); ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data"), &RenderingDevice::index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false)); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index f1f8b3cda0..787805ea6a 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -392,7 +392,7 @@ public: uint32_t depth; uint32_t array_layers; uint32_t mipmaps; - TextureType type; + TextureType texture_type; TextureSamples samples; uint32_t usage_bits; Vector<DataFormat> shareable_formats; @@ -404,7 +404,7 @@ public: depth = 1; array_layers = 1; mipmaps = 1; - type = TEXTURE_TYPE_2D; + texture_type = TEXTURE_TYPE_2D; samples = TEXTURE_SAMPLES_1; usage_bits = 0; } @@ -433,6 +433,7 @@ public: TEXTURE_SLICE_2D, TEXTURE_SLICE_CUBEMAP, TEXTURE_SLICE_3D, + TEXTURE_SLICE_2D_ARRAY, }; virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0; @@ -564,7 +565,7 @@ public: frequency = VERTEX_FREQUENCY_VERTEX; } }; - virtual RID vertex_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0; + virtual RID vertex_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>(), bool p_use_as_storage = false) = 0; typedef int64_t VertexFormatID; @@ -629,7 +630,7 @@ public: virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0; struct Uniform { - UniformType type; + UniformType uniform_type; int binding; //binding index as specified in shader //for single items, provide one ID, for @@ -640,7 +641,7 @@ public: Vector<RID> ids; Uniform() { - type = UNIFORM_TYPE_IMAGE; + uniform_type = UNIFORM_TYPE_IMAGE; binding = 0; } }; diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp index af9ecef0dd..2f11360364 100644 --- a/servers/rendering/rendering_device_binds.cpp +++ b/servers/rendering/rendering_device_binds.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -163,7 +163,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "When writing compute shaders, [compute] mustbe the only stage present."); } - if (version_texts.empty()) { + if (version_texts.is_empty()) { version_texts[""] = ""; //make sure a default version exists } diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h index 66c6a1c3a9..e43c3669b5 100644 --- a/servers/rendering/rendering_device_binds.h +++ b/servers/rendering/rendering_device_binds.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -64,7 +64,7 @@ public: RD_SETGET(uint32_t, depth) RD_SETGET(uint32_t, array_layers) RD_SETGET(uint32_t, mipmaps) - RD_SETGET(RD::TextureType, type) + RD_SETGET(RD::TextureType, texture_type) RD_SETGET(RD::TextureSamples, samples) RD_SETGET(uint32_t, usage_bits) @@ -79,7 +79,7 @@ protected: RD_BIND(Variant::INT, RDTextureFormat, depth); RD_BIND(Variant::INT, RDTextureFormat, array_layers); RD_BIND(Variant::INT, RDTextureFormat, mipmaps); - RD_BIND(Variant::INT, RDTextureFormat, type); + RD_BIND(Variant::INT, RDTextureFormat, texture_type); RD_BIND(Variant::INT, RDTextureFormat, samples); RD_BIND(Variant::INT, RDTextureFormat, usage_bits); ClassDB::bind_method(D_METHOD("add_shareable_format", "format"), &RDTextureFormat::add_shareable_format); @@ -392,7 +392,7 @@ class RDUniform : public Reference { RD::Uniform base; public: - RD_SETGET(RD::UniformType, type) + RD_SETGET(RD::UniformType, uniform_type) RD_SETGET(int32_t, binding) void add_id(const RID &p_id) { base.ids.push_back(p_id); } @@ -415,7 +415,7 @@ protected: } } static void _bind_methods() { - RD_BIND(Variant::INT, RDUniform, type); + RD_BIND(Variant::INT, RDUniform, uniform_type); RD_BIND(Variant::INT, RDUniform, binding); ClassDB::bind_method(D_METHOD("add_id", "id"), &RDUniform::add_id); ClassDB::bind_method(D_METHOD("clear_ids"), &RDUniform::clear_ids); diff --git a/servers/rendering/rendering_server_raster.cpp b/servers/rendering/rendering_server_default.cpp index 94cfb6b752..8c6e97a0af 100644 --- a/servers/rendering/rendering_server_raster.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rendering_server_raster.cpp */ +/* rendering_server_default.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,43 +28,43 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "rendering_server_raster.h" +#include "rendering_server_default.h" #include "core/config/project_settings.h" #include "core/io/marshalls.h" #include "core/os/os.h" #include "core/templates/sort_array.h" -#include "rendering_server_canvas.h" +#include "renderer_canvas_cull.h" +#include "renderer_scene_cull.h" #include "rendering_server_globals.h" -#include "rendering_server_scene.h" // careful, these may run in different threads than the visual server -int RenderingServerRaster::changes = 0; +int RenderingServerDefault::changes = 0; /* BLACK BARS */ -void RenderingServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) { - black_margin[MARGIN_LEFT] = p_left; - black_margin[MARGIN_TOP] = p_top; - black_margin[MARGIN_RIGHT] = p_right; - black_margin[MARGIN_BOTTOM] = p_bottom; +void RenderingServerDefault::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) { + black_margin[SIDE_LEFT] = p_left; + black_margin[SIDE_TOP] = p_top; + black_margin[SIDE_RIGHT] = p_right; + black_margin[SIDE_BOTTOM] = p_bottom; } -void RenderingServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) { - black_image[MARGIN_LEFT] = p_left; - black_image[MARGIN_TOP] = p_top; - black_image[MARGIN_RIGHT] = p_right; - black_image[MARGIN_BOTTOM] = p_bottom; +void RenderingServerDefault::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) { + black_image[SIDE_LEFT] = p_left; + black_image[SIDE_TOP] = p_top; + black_image[SIDE_RIGHT] = p_right; + black_image[SIDE_BOTTOM] = p_bottom; } -void RenderingServerRaster::_draw_margins() { +void RenderingServerDefault::_draw_margins() { RSG::canvas_render->draw_window_margins(black_margin, black_image); }; /* FREE */ -void RenderingServerRaster::free(RID p_rid) { +void RenderingServerDefault::free(RID p_rid) { if (RSG::storage->free(p_rid)) { return; } @@ -77,14 +77,11 @@ void RenderingServerRaster::free(RID p_rid) { if (RSG::scene->free(p_rid)) { return; } - if (RSG::scene_render->free(p_rid)) { - return; - } } /* EVENT QUEUING */ -void RenderingServerRaster::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) { +void RenderingServerDefault::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) { ERR_FAIL_NULL(p_where); FrameDrawnCallbacks fdc; fdc.object = p_where->get_instance_id(); @@ -94,7 +91,7 @@ void RenderingServerRaster::request_frame_drawn_callback(Object *p_where, const frame_drawn_callbacks.push_back(fdc); } -void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) { +void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) { //needs to be done before changes is reset to 0, to not force the editor to redraw RS::get_singleton()->emit_signal("frame_pre_draw"); @@ -104,14 +101,16 @@ void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) { TIMESTAMP_BEGIN() - RSG::scene_render->update(); //update scenes stuff before updating instances + uint64_t time_usec = OS::get_singleton()->get_ticks_usec(); + + RSG::scene->update(); //update scenes stuff before updating instances - RSG::scene->update_dirty_instances(); //update scene stuff + frame_setup_time = double(OS::get_singleton()->get_ticks_usec() - time_usec) / 1000.0; - RSG::scene->render_particle_colliders(); RSG::storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered RSG::scene->render_probes(); + RSG::viewport->draw_viewports(); RSG::canvas_render->update(); @@ -165,18 +164,22 @@ void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) { frame_profile_frame = RSG::storage->get_captured_timestamps_frame(); } -void RenderingServerRaster::sync() { +float RenderingServerDefault::get_frame_setup_time_cpu() const { + return frame_setup_time; +} + +void RenderingServerDefault::sync() { } -bool RenderingServerRaster::has_changed() const { +bool RenderingServerDefault::has_changed() const { return changes > 0; } -void RenderingServerRaster::init() { +void RenderingServerDefault::init() { RSG::rasterizer->initialize(); } -void RenderingServerRaster::finish() { +void RenderingServerDefault::finish() { if (test_cube.is_valid()) { free(test_cube); } @@ -186,69 +189,69 @@ void RenderingServerRaster::finish() { /* STATUS INFORMATION */ -int RenderingServerRaster::get_render_info(RenderInfo p_info) { +int RenderingServerDefault::get_render_info(RenderInfo p_info) { return RSG::storage->get_render_info(p_info); } -String RenderingServerRaster::get_video_adapter_name() const { +String RenderingServerDefault::get_video_adapter_name() const { return RSG::storage->get_video_adapter_name(); } -String RenderingServerRaster::get_video_adapter_vendor() const { +String RenderingServerDefault::get_video_adapter_vendor() const { return RSG::storage->get_video_adapter_vendor(); } -void RenderingServerRaster::set_frame_profiling_enabled(bool p_enable) { +void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) { RSG::storage->capturing_timestamps = p_enable; } -uint64_t RenderingServerRaster::get_frame_profile_frame() { +uint64_t RenderingServerDefault::get_frame_profile_frame() { return frame_profile_frame; } -Vector<RenderingServer::FrameProfileArea> RenderingServerRaster::get_frame_profile() { +Vector<RenderingServer::FrameProfileArea> RenderingServerDefault::get_frame_profile() { return frame_profile; } /* TESTING */ -void RenderingServerRaster::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { +void RenderingServerDefault::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { redraw_request(); RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter); } -void RenderingServerRaster::set_default_clear_color(const Color &p_color) { +void RenderingServerDefault::set_default_clear_color(const Color &p_color) { RSG::viewport->set_default_clear_color(p_color); } -bool RenderingServerRaster::has_feature(Features p_feature) const { +bool RenderingServerDefault::has_feature(Features p_feature) const { return false; } -void RenderingServerRaster::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { - RSG::scene_render->sdfgi_set_debug_probe_select(p_position, p_dir); +void RenderingServerDefault::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { + RSG::scene->sdfgi_set_debug_probe_select(p_position, p_dir); } -RID RenderingServerRaster::get_test_cube() { +RID RenderingServerDefault::get_test_cube() { if (!test_cube.is_valid()) { test_cube = _make_test_cube(); } return test_cube; } -bool RenderingServerRaster::has_os_feature(const String &p_feature) const { +bool RenderingServerDefault::has_os_feature(const String &p_feature) const { return RSG::storage->has_os_feature(p_feature); } -void RenderingServerRaster::set_debug_generate_wireframes(bool p_generate) { +void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) { RSG::storage->set_debug_generate_wireframes(p_generate); } -void RenderingServerRaster::call_set_use_vsync(bool p_enable) { +void RenderingServerDefault::call_set_use_vsync(bool p_enable) { DisplayServer::get_singleton()->_set_use_vsync(p_enable); } -bool RenderingServerRaster::is_low_end() const { +bool RenderingServerDefault::is_low_end() const { // FIXME: Commented out when rebasing vulkan branch on master, // causes a crash, it seems rasterizer is not initialized yet the // first time it's called. @@ -256,14 +259,15 @@ bool RenderingServerRaster::is_low_end() const { return false; } -RenderingServerRaster::RenderingServerRaster() { - RSG::canvas = memnew(RenderingServerCanvas); - RSG::viewport = memnew(RenderingServerViewport); - RSG::scene = memnew(RenderingServerScene); - RSG::rasterizer = Rasterizer::create(); +RenderingServerDefault::RenderingServerDefault() { + RSG::canvas = memnew(RendererCanvasCull); + RSG::viewport = memnew(RendererViewport); + RendererSceneCull *sr = memnew(RendererSceneCull); + RSG::scene = sr; + RSG::rasterizer = RendererCompositor::create(); RSG::storage = RSG::rasterizer->get_storage(); RSG::canvas_render = RSG::rasterizer->get_canvas(); - RSG::scene_render = RSG::rasterizer->get_scene(); + sr->set_scene_render(RSG::rasterizer->get_scene()); frame_profile_frame = 0; @@ -273,7 +277,7 @@ RenderingServerRaster::RenderingServerRaster() { } } -RenderingServerRaster::~RenderingServerRaster() { +RenderingServerDefault::~RenderingServerDefault() { memdelete(RSG::canvas); memdelete(RSG::viewport); memdelete(RSG::rasterizer); diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_default.h index 413fcda581..71f459f34a 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_default.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* rendering_server_raster.h */ +/* rendering_server_default.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -28,18 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_RASTER_H -#define RENDERING_SERVER_RASTER_H +#ifndef RENDERING_SERVER_DEFAULT_H +#define RENDERING_SERVER_DEFAULT_H #include "core/math/octree.h" -#include "rendering_server_canvas.h" +#include "renderer_canvas_cull.h" +#include "renderer_scene_cull.h" +#include "renderer_viewport.h" #include "rendering_server_globals.h" -#include "rendering_server_scene.h" -#include "rendering_server_viewport.h" -#include "servers/rendering/rasterizer.h" +#include "servers/rendering/renderer_compositor.h" #include "servers/rendering_server.h" -class RenderingServerRaster : public RenderingServer { +class RenderingServerDefault : public RenderingServer { enum { MAX_INSTANCE_CULL = 8192, MAX_INSTANCE_LIGHTS = 4, @@ -72,6 +72,8 @@ class RenderingServerRaster : public RenderingServer { uint64_t frame_profile_frame; Vector<FrameProfileArea> frame_profile; + float frame_setup_time = 0; + public: //if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed() //#define DEBUG_CHANGES @@ -217,6 +219,8 @@ public: BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &) BIND2RC(Variant, shader_get_param_default, RID, const StringName &) + BIND1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID) + /* COMMON MATERIAL API */ BIND0R(RID, material_create) @@ -231,14 +235,17 @@ public: /* MESH API */ - virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces) { + virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) { RID mesh = mesh_create(); + mesh_set_blend_shape_count(mesh, p_blend_shape_count); for (int i = 0; i < p_surfaces.size(); i++) { mesh_add_surface(mesh, p_surfaces[i]); } return mesh; } + BIND2(mesh_set_blend_shape_count, RID, int) + BIND0R(RID, mesh_create) BIND2(mesh_add_surface, RID, const SurfaceData &) @@ -336,6 +343,7 @@ public: BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) BIND2(light_directional_set_blend_splits, RID, bool) + BIND2(light_directional_set_sky_only, RID, bool) BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) /* PROBE API */ @@ -355,6 +363,7 @@ public: BIND2(reflection_probe_set_enable_shadows, RID, bool) BIND2(reflection_probe_set_cull_mask, RID, uint32_t) BIND2(reflection_probe_set_resolution, RID, int) + BIND2(reflection_probe_set_lod_threshold, RID, float) /* DECAL API */ @@ -541,6 +550,7 @@ public: BIND2(viewport_set_msaa, RID, ViewportMSAA) BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) BIND2(viewport_set_use_debanding, RID, bool) + BIND2(viewport_set_lod_threshold, RID, float) BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo) BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw) @@ -553,7 +563,7 @@ public: #undef BINDBASE //from now on, calls forwarded to this singleton -#define BINDBASE RSG::scene_render +#define BINDBASE RSG::scene BIND1(directional_shadow_atlas_set_size, int) BIND1(gi_probe_set_quality, GIProbeQuality) @@ -584,8 +594,8 @@ public: BIND6(environment_set_ssr, RID, bool, int, float, float, float) BIND1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality) - BIND9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) - BIND2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) + BIND10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float) + BIND6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float) BIND11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) BIND1(environment_glow_set_use_bicubic_upscale, bool) @@ -593,7 +603,7 @@ public: BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) - BIND6(environment_set_adjustment, RID, bool, float, float, float, RID) + BIND7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) BIND9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) BIND9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter) @@ -669,6 +679,7 @@ public: BIND5(instance_geometry_set_draw_range, RID, float, float, float, float) BIND2(instance_geometry_set_as_instance_lod, RID, RID) BIND4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int) + BIND2(instance_geometry_set_lod_bias, RID, float) BIND3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &) BIND2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &) @@ -717,7 +728,7 @@ public: BIND2(canvas_item_set_draw_behind_parent, RID, bool) BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) - BIND4(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float) + BIND5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) BIND4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float) BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &) BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) @@ -838,6 +849,8 @@ public: /* TESTING */ + virtual float get_frame_setup_time_cpu() const; + virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true); virtual void set_default_clear_color(const Color &p_color); @@ -852,8 +865,8 @@ public: virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir); - RenderingServerRaster(); - ~RenderingServerRaster(); + RenderingServerDefault(); + ~RenderingServerDefault(); #undef DISPLAY_CHANGED diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp index 5a270520a9..c0d9988e85 100644 --- a/servers/rendering/rendering_server_globals.cpp +++ b/servers/rendering/rendering_server_globals.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -30,11 +30,10 @@ #include "rendering_server_globals.h" -RasterizerStorage *RenderingServerGlobals::storage = nullptr; -RasterizerCanvas *RenderingServerGlobals::canvas_render = nullptr; -RasterizerScene *RenderingServerGlobals::scene_render = nullptr; -Rasterizer *RenderingServerGlobals::rasterizer = nullptr; +RendererStorage *RenderingServerGlobals::storage = nullptr; +RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr; +RendererCompositor *RenderingServerGlobals::rasterizer = nullptr; -RenderingServerCanvas *RenderingServerGlobals::canvas = nullptr; -RenderingServerViewport *RenderingServerGlobals::viewport = nullptr; -RenderingServerScene *RenderingServerGlobals::scene = nullptr; +RendererCanvasCull *RenderingServerGlobals::canvas = nullptr; +RendererViewport *RenderingServerGlobals::viewport = nullptr; +RendererScene *RenderingServerGlobals::scene = nullptr; diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h index b33f328b69..a28a0f5180 100644 --- a/servers/rendering/rendering_server_globals.h +++ b/servers/rendering/rendering_server_globals.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -31,22 +31,23 @@ #ifndef RENDERING_SERVER_GLOBALS_H #define RENDERING_SERVER_GLOBALS_H -#include "rasterizer.h" +#include "servers/rendering/renderer_canvas_cull.h" +#include "servers/rendering/renderer_canvas_render.h" +#include "servers/rendering/renderer_scene.h" -class RenderingServerCanvas; -class RenderingServerViewport; -class RenderingServerScene; +class RendererCanvasCull; +class RendererViewport; +class RendererScene; class RenderingServerGlobals { public: - static RasterizerStorage *storage; - static RasterizerCanvas *canvas_render; - static RasterizerScene *scene_render; - static Rasterizer *rasterizer; + static RendererStorage *storage; + static RendererCanvasRender *canvas_render; + static RendererCompositor *rasterizer; - static RenderingServerCanvas *canvas; - static RenderingServerViewport *viewport; - static RenderingServerScene *scene; + static RendererCanvasCull *canvas; + static RendererViewport *viewport; + static RendererScene *scene; }; #define RSG RenderingServerGlobals diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp deleted file mode 100644 index ae6786090a..0000000000 --- a/servers/rendering/rendering_server_scene.cpp +++ /dev/null @@ -1,3040 +0,0 @@ -/*************************************************************************/ -/* rendering_server_scene.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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. */ -/*************************************************************************/ - -#include "rendering_server_scene.h" - -#include "core/os/os.h" -#include "rendering_server_globals.h" -#include "rendering_server_raster.h" - -#include <new> - -/* CAMERA API */ - -RID RenderingServerScene::camera_create() { - Camera *camera = memnew(Camera); - return camera_owner.make_rid(camera); -} - -void RenderingServerScene::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->type = Camera::PERSPECTIVE; - camera->fov = p_fovy_degrees; - camera->znear = p_z_near; - camera->zfar = p_z_far; -} - -void RenderingServerScene::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->type = Camera::ORTHOGONAL; - camera->size = p_size; - camera->znear = p_z_near; - camera->zfar = p_z_far; -} - -void RenderingServerScene::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->type = Camera::FRUSTUM; - camera->size = p_size; - camera->offset = p_offset; - camera->znear = p_z_near; - camera->zfar = p_z_far; -} - -void RenderingServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->transform = p_transform.orthonormalized(); -} - -void RenderingServerScene::camera_set_cull_mask(RID p_camera, uint32_t p_layers) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - - camera->visible_layers = p_layers; -} - -void RenderingServerScene::camera_set_environment(RID p_camera, RID p_env) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->env = p_env; -} - -void RenderingServerScene::camera_set_camera_effects(RID p_camera, RID p_fx) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->effects = p_fx; -} - -void RenderingServerScene::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->vaspect = p_enable; -} - -/* SCENARIO API */ - -void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int) { - //RenderingServerScene *self = (RenderingServerScene*)p_self; - Instance *A = p_A; - Instance *B = p_B; - - //instance indices are designed so greater always contains lesser - if (A->base_type > B->base_type) { - SWAP(A, B); //lesser always first - } - - if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - InstanceLightData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->lighting.push_back(B); - - List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo); - - if (geom->can_cast_shadows) { - light->shadow_dirty = true; - } - geom->lighting_dirty = true; - - return E; //this element should make freeing faster - } else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - InstanceReflectionProbeData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->reflection_probes.push_back(B); - - List<InstanceReflectionProbeData::PairInfo>::Element *E = reflection_probe->geometries.push_back(pinfo); - - geom->reflection_dirty = true; - - return E; //this element should make freeing faster - } else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - InstanceDecalData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->decals.push_back(B); - - List<InstanceDecalData::PairInfo>::Element *E = decal->geometries.push_back(pinfo); - - geom->decal_dirty = true; - - return E; //this element should make freeing faster - } else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - if (A->dynamic_gi) { - InstanceLightmapData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->lightmap_captures.push_back(B); - List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.push_back(pinfo); - ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture - return E; //this element should make freeing faster - } else { - return nullptr; - } - - } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - InstanceGIProbeData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->gi_probes.push_back(B); - - List<InstanceGIProbeData::PairInfo>::Element *E; - if (A->dynamic_gi) { - E = gi_probe->dynamic_geometries.push_back(pinfo); - } else { - E = gi_probe->geometries.push_back(pinfo); - } - - geom->gi_probes_dirty = true; - - return E; //this element should make freeing faster - - } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); - return gi_probe->lights.insert(A); - } else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) { - RSG::storage->particles_add_collision(A->base, B); - } - - return nullptr; -} - -void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *udata) { - //RenderingServerScene *self = (RenderingServerScene*)p_self; - Instance *A = p_A; - Instance *B = p_B; - - //instance indices are designed so greater always contains lesser - if (A->base_type > B->base_type) { - SWAP(A, B); //lesser always first - } - - if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceLightData *light = static_cast<InstanceLightData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - List<InstanceLightData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightData::PairInfo>::Element *>(udata); - - geom->lighting.erase(E->get().L); - light->geometries.erase(E); - - if (geom->can_cast_shadows) { - light->shadow_dirty = true; - } - geom->lighting_dirty = true; - - } else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - List<InstanceReflectionProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceReflectionProbeData::PairInfo>::Element *>(udata); - - geom->reflection_probes.erase(E->get().L); - reflection_probe->geometries.erase(E); - - geom->reflection_dirty = true; - } else if (B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - List<InstanceDecalData::PairInfo>::Element *E = reinterpret_cast<List<InstanceDecalData::PairInfo>::Element *>(udata); - - geom->decals.erase(E->get().L); - decal->geometries.erase(E); - - geom->decal_dirty = true; - } else if (B->base_type == RS::INSTANCE_LIGHTMAP && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - if (udata) { //only for dynamic geometries - InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - List<InstanceLightmapData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightmapData::PairInfo>::Element *>(udata); - - geom->lightmap_captures.erase(E->get().L); - lightmap_data->geometries.erase(E); - ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture - } - - } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data); - - List<InstanceGIProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceGIProbeData::PairInfo>::Element *>(udata); - - geom->gi_probes.erase(E->get().L); - if (A->dynamic_gi) { - gi_probe->dynamic_geometries.erase(E); - } else { - gi_probe->geometries.erase(E); - } - - geom->gi_probes_dirty = true; - - } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data); - Set<Instance *>::Element *E = reinterpret_cast<Set<Instance *>::Element *>(udata); - - gi_probe->lights.erase(E); - } else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) { - RSG::storage->particles_remove_collision(A->base, B); - } -} - -RID RenderingServerScene::scenario_create() { - Scenario *scenario = memnew(Scenario); - ERR_FAIL_COND_V(!scenario, RID()); - RID scenario_rid = scenario_owner.make_rid(scenario); - scenario->self = scenario_rid; - - scenario->octree.set_pair_callback(_instance_pair, this); - scenario->octree.set_unpair_callback(_instance_unpair, this); - scenario->reflection_probe_shadow_atlas = RSG::scene_render->shadow_atlas_create(); - RSG::scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest - RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4); - RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4); - RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4); - RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8); - scenario->reflection_atlas = RSG::scene_render->reflection_atlas_create(); - return scenario_rid; -} - -void RenderingServerScene::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) { - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->debug = p_debug_mode; -} - -void RenderingServerScene::scenario_set_environment(RID p_scenario, RID p_environment) { - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->environment = p_environment; -} - -void RenderingServerScene::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) { - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->camera_effects = p_camera_effects; -} - -void RenderingServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->fallback_environment = p_environment; -} - -void RenderingServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) { - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - RSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count); -} - -/* INSTANCING API */ - -void RenderingServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) { - if (p_update_aabb) { - p_instance->update_aabb = true; - } - if (p_update_dependencies) { - p_instance->update_dependencies = true; - } - - if (p_instance->update_item.in_list()) { - return; - } - - _instance_update_list.add(&p_instance->update_item); -} - -RID RenderingServerScene::instance_create() { - Instance *instance = memnew(Instance); - ERR_FAIL_COND_V(!instance, RID()); - - RID instance_rid = instance_owner.make_rid(instance); - instance->self = instance_rid; - - return instance_rid; -} - -void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - Scenario *scenario = instance->scenario; - - if (instance->base_type != RS::INSTANCE_NONE) { - //free anything related to that base - - if (scenario && instance->octree_id) { - scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away - instance->octree_id = 0; - } - - switch (instance->base_type) { - case RS::INSTANCE_LIGHT: { - InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); - - if (scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { - scenario->dynamic_lights.erase(light->instance); - } - -#ifdef DEBUG_ENABLED - if (light->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from light."); - } -#endif - if (scenario && light->D) { - scenario->directional_lights.erase(light->D); - light->D = nullptr; - } - RSG::scene_render->free(light->instance); - } break; - case RS::INSTANCE_REFLECTION_PROBE: { - InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data); - RSG::scene_render->free(reflection_probe->instance); - if (reflection_probe->update_list.in_list()) { - reflection_probe_render_list.remove(&reflection_probe->update_list); - } - } break; - case RS::INSTANCE_DECAL: { - InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data); - RSG::scene_render->free(decal->instance); - - } break; - case RS::INSTANCE_LIGHTMAP: { - InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(instance->base_data); - //erase dependencies, since no longer a lightmap - while (lightmap_data->users.front()) { - instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0); - } - } break; - case RS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data); -#ifdef DEBUG_ENABLED - if (gi_probe->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); - } -#endif -#ifdef DEBUG_ENABLED - if (gi_probe->lights.size()) { - ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); - } -#endif - if (gi_probe->update_element.in_list()) { - gi_probe_update_list.remove(&gi_probe->update_element); - } - - RSG::scene_render->free(gi_probe->probe_instance); - - } break; - default: { - } - } - - if (instance->base_data) { - memdelete(instance->base_data); - instance->base_data = nullptr; - } - - instance->blend_values.clear(); - instance->materials.clear(); - } - - instance->base_type = RS::INSTANCE_NONE; - instance->base = RID(); - - if (p_base.is_valid()) { - instance->base_type = RSG::storage->get_base_type(p_base); - ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE); - - switch (instance->base_type) { - case RS::INSTANCE_LIGHT: { - InstanceLightData *light = memnew(InstanceLightData); - - if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) { - light->D = scenario->directional_lights.push_back(instance); - } - - light->instance = RSG::scene_render->light_instance_create(p_base); - - instance->base_data = light; - } break; - case RS::INSTANCE_MESH: - case RS::INSTANCE_MULTIMESH: - case RS::INSTANCE_IMMEDIATE: - case RS::INSTANCE_PARTICLES: { - InstanceGeometryData *geom = memnew(InstanceGeometryData); - instance->base_data = geom; - if (instance->base_type == RS::INSTANCE_MESH) { - instance->blend_values.resize(RSG::storage->mesh_get_blend_shape_count(p_base)); - } - } break; - case RS::INSTANCE_REFLECTION_PROBE: { - InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData); - reflection_probe->owner = instance; - instance->base_data = reflection_probe; - - reflection_probe->instance = RSG::scene_render->reflection_probe_instance_create(p_base); - } break; - case RS::INSTANCE_DECAL: { - InstanceDecalData *decal = memnew(InstanceDecalData); - decal->owner = instance; - instance->base_data = decal; - - decal->instance = RSG::scene_render->decal_instance_create(p_base); - } break; - case RS::INSTANCE_LIGHTMAP: { - InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData); - instance->base_data = lightmap_data; - //lightmap_data->instance = RSG::scene_render->lightmap_data_instance_create(p_base); - } break; - case RS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData); - instance->base_data = gi_probe; - gi_probe->owner = instance; - - if (scenario && !gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - - gi_probe->probe_instance = RSG::scene_render->gi_probe_instance_create(p_base); - - } break; - default: { - } - } - - instance->base = p_base; - - //forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it - RSG::storage->base_update_dependency(p_base, instance); - } - - _instance_queue_update(instance, true, true); -} - -void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->scenario) { - instance->scenario->instances.remove(&instance->scenario_item); - - if (instance->octree_id) { - instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away - instance->octree_id = 0; - } - - switch (instance->base_type) { - case RS::INSTANCE_LIGHT: { - InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); -#ifdef DEBUG_ENABLED - if (light->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from light."); - } -#endif - if (light->D) { - instance->scenario->directional_lights.erase(light->D); - light->D = nullptr; - } - } break; - case RS::INSTANCE_REFLECTION_PROBE: { - InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data); - RSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance); - - } break; - case RS::INSTANCE_PARTICLES_COLLISION: { - heightfield_particle_colliders_update_list.erase(instance); - } break; - case RS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data); - -#ifdef DEBUG_ENABLED - if (gi_probe->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); - } -#endif -#ifdef DEBUG_ENABLED - if (gi_probe->lights.size()) { - ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); - } -#endif - - if (gi_probe->update_element.in_list()) { - gi_probe_update_list.remove(&gi_probe->update_element); - } - } break; - default: { - } - } - - instance->scenario = nullptr; - } - - if (p_scenario.is_valid()) { - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - - instance->scenario = scenario; - - scenario->instances.add(&instance->scenario_item); - - switch (instance->base_type) { - case RS::INSTANCE_LIGHT: { - InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); - - if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) { - light->D = scenario->directional_lights.push_back(instance); - } - } break; - case RS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data); - if (!gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - } break; - default: { - } - } - - _instance_queue_update(instance, true, true); - } -} - -void RenderingServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->layer_mask = p_mask; -} - -void RenderingServerScene::instance_set_transform(RID p_instance, const Transform &p_transform) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->transform == p_transform) { - return; //must be checked to avoid worst evil - } - -#ifdef DEBUG_ENABLED - - for (int i = 0; i < 4; i++) { - const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin; - ERR_FAIL_COND(Math::is_inf(v.x)); - ERR_FAIL_COND(Math::is_nan(v.x)); - ERR_FAIL_COND(Math::is_inf(v.y)); - ERR_FAIL_COND(Math::is_nan(v.y)); - ERR_FAIL_COND(Math::is_inf(v.z)); - ERR_FAIL_COND(Math::is_nan(v.z)); - } - -#endif - instance->transform = p_transform; - _instance_queue_update(instance, true); -} - -void RenderingServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->object_id = p_id; -} - -void RenderingServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->update_item.in_list()) { - _update_dirty_instance(instance); - } - - ERR_FAIL_INDEX(p_shape, instance->blend_values.size()); - instance->blend_values.write[p_shape] = p_weight; -} - -void RenderingServerScene::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->base_type == RS::INSTANCE_MESH) { - //may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case - instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base))); - } - - ERR_FAIL_INDEX(p_surface, instance->materials.size()); - - instance->materials.write[p_surface] = p_material; - - _instance_queue_update(instance, false, true); -} - -void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->visible == p_visible) { - return; - } - - instance->visible = p_visible; - - switch (instance->base_type) { - case RS::INSTANCE_LIGHT: { - if (RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHT, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); - } - - } break; - case RS::INSTANCE_REFLECTION_PROBE: { - if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); - } - - } break; - case RS::INSTANCE_DECAL: { - if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_DECAL, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); - } - - } break; - case RS::INSTANCE_LIGHTMAP: { - if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); - } - - } break; - case RS::INSTANCE_GI_PROBE: { - if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_GI_PROBE, p_visible ? (RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT)) : 0); - } - - } break; - case RS::INSTANCE_PARTICLES_COLLISION: { - if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_PARTICLES_COLLISION, p_visible ? (1 << RS::INSTANCE_PARTICLES) : 0); - } - - } break; - default: { - } - } -} - -inline bool is_geometry_instance(RenderingServer::InstanceType p_type) { - return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE; -} - -void RenderingServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - ERR_FAIL_COND(!is_geometry_instance(instance->base_type)); - - if (p_aabb != AABB()) { - // Set custom AABB - if (instance->custom_aabb == nullptr) { - instance->custom_aabb = memnew(AABB); - } - *instance->custom_aabb = p_aabb; - - } else { - // Clear custom AABB - if (instance->custom_aabb != nullptr) { - memdelete(instance->custom_aabb); - instance->custom_aabb = nullptr; - } - } - - if (instance->scenario) { - _instance_queue_update(instance, true, false); - } -} - -void RenderingServerScene::instance_attach_skeleton(RID p_instance, RID p_skeleton) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->skeleton == p_skeleton) { - return; - } - - instance->skeleton = p_skeleton; - - if (p_skeleton.is_valid()) { - //update the dependency now, so if cleared, we remove it - RSG::storage->skeleton_update_dependency(p_skeleton, instance); - } - _instance_queue_update(instance, true, true); -} - -void RenderingServerScene::instance_set_exterior(RID p_instance, bool p_enabled) { -} - -void RenderingServerScene::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->extra_margin = p_margin; - _instance_queue_update(instance, true, false); -} - -Vector<ObjectID> RenderingServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const { - Vector<ObjectID> instances; - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND_V(!scenario, instances); - - const_cast<RenderingServerScene *>(this)->update_dirty_instances(); // check dirty instances before culling - - int culled = 0; - Instance *cull[1024]; - culled = scenario->octree.cull_aabb(p_aabb, cull, 1024); - - for (int i = 0; i < culled; i++) { - Instance *instance = cull[i]; - ERR_CONTINUE(!instance); - if (instance->object_id.is_null()) { - continue; - } - - instances.push_back(instance->object_id); - } - - return instances; -} - -Vector<ObjectID> RenderingServerScene::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { - Vector<ObjectID> instances; - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND_V(!scenario, instances); - const_cast<RenderingServerScene *>(this)->update_dirty_instances(); // check dirty instances before culling - - int culled = 0; - Instance *cull[1024]; - culled = scenario->octree.cull_segment(p_from, p_from + p_to * 10000, cull, 1024); - - for (int i = 0; i < culled; i++) { - Instance *instance = cull[i]; - ERR_CONTINUE(!instance); - if (instance->object_id.is_null()) { - continue; - } - - instances.push_back(instance->object_id); - } - - return instances; -} - -Vector<ObjectID> RenderingServerScene::instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario) const { - Vector<ObjectID> instances; - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND_V(!scenario, instances); - const_cast<RenderingServerScene *>(this)->update_dirty_instances(); // check dirty instances before culling - - int culled = 0; - Instance *cull[1024]; - - culled = scenario->octree.cull_convex(p_convex, cull, 1024); - - for (int i = 0; i < culled; i++) { - Instance *instance = cull[i]; - ERR_CONTINUE(!instance); - if (instance->object_id.is_null()) { - continue; - } - - instances.push_back(instance->object_id); - } - - return instances; -} - -void RenderingServerScene::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - //ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK)); - - switch (p_flags) { - case RS::INSTANCE_FLAG_USE_BAKED_LIGHT: { - instance->baked_light = p_enabled; - - } break; - case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: { - if (p_enabled == instance->dynamic_gi) { - //bye, redundant - return; - } - - if (instance->octree_id != 0) { - //remove from octree, it needs to be re-paired - instance->scenario->octree.erase(instance->octree_id); - instance->octree_id = 0; - _instance_queue_update(instance, true, true); - } - - //once out of octree, can be changed - instance->dynamic_gi = p_enabled; - - } break; - case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: { - instance->redraw_if_visible = p_enabled; - - } break; - default: { - } - } -} - -void RenderingServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->cast_shadows = p_shadow_casting_setting; - _instance_queue_update(instance, false, true); -} - -void RenderingServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->material_override = p_material; - _instance_queue_update(instance, false, true); -} - -void RenderingServerScene::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) { -} - -void RenderingServerScene::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) { -} - -void RenderingServerScene::instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->lightmap) { - InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(((Instance *)instance->lightmap)->base_data); - lightmap_data->users.erase(instance); - instance->lightmap = nullptr; - } - - Instance *lightmap_instance = instance_owner.getornull(p_lightmap); - - instance->lightmap = lightmap_instance; - instance->lightmap_uv_scale = p_lightmap_uv_scale; - instance->lightmap_slice_index = p_slice_index; - - if (lightmap_instance) { - InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data); - lightmap_data->users.insert(instance); - } -} - -void RenderingServerScene::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter); - - if (!E) { - RasterizerScene::InstanceBase::InstanceShaderParameter isp; - isp.index = -1; - isp.info = PropertyInfo(); - isp.value = p_value; - instance->instance_shader_parameters[p_parameter] = isp; - } else { - E->get().value = p_value; - if (E->get().index >= 0 && instance->instance_allocated_shader_parameters) { - //update directly - RSG::storage->global_variables_instance_update(p_instance, E->get().index, p_value); - } - } -} - -Variant RenderingServerScene::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const { - const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!instance, Variant()); - - if (instance->instance_shader_parameters.has(p_parameter)) { - return instance->instance_shader_parameters[p_parameter].value; - } - return Variant(); -} - -Variant RenderingServerScene::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const { - const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!instance, Variant()); - - if (instance->instance_shader_parameters.has(p_parameter)) { - return instance->instance_shader_parameters[p_parameter].default_value; - } - return Variant(); -} - -void RenderingServerScene::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const { - const Instance *instance = const_cast<RenderingServerScene *>(this)->instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - const_cast<RenderingServerScene *>(this)->update_dirty_instances(); - - Vector<StringName> names; - for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) { - names.push_back(E->key()); - } - names.sort_custom<StringName::AlphCompare>(); - for (int i = 0; i < names.size(); i++) { - PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info; - p_parameters->push_back(pinfo); - } -} - -void RenderingServerScene::_update_instance(Instance *p_instance) { - p_instance->version++; - - if (p_instance->base_type == RS::INSTANCE_LIGHT) { - InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); - - RSG::scene_render->light_instance_set_transform(light->instance, p_instance->transform); - RSG::scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb)); - light->shadow_dirty = true; - - RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base); - if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) { - if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { - p_instance->scenario->dynamic_lights.erase(light->instance); - } - - light->bake_mode = bake_mode; - - if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { - p_instance->scenario->dynamic_lights.push_back(light->instance); - } - } - - uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base); - if (light->max_sdfgi_cascade != max_sdfgi_cascade) { - light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario - } - } - - if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) { - InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data); - - RSG::scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform); - reflection_probe->reflection_dirty = true; - } - - if (p_instance->base_type == RS::INSTANCE_DECAL) { - InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data); - - RSG::scene_render->decal_instance_set_transform(decal->instance, p_instance->transform); - } - - if (p_instance->base_type == RS::INSTANCE_GI_PROBE) { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data); - - RSG::scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform); - } - - if (p_instance->base_type == RS::INSTANCE_PARTICLES) { - RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform); - } - - if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { - //remove materials no longer used and un-own them - if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) { - heightfield_particle_colliders_update_list.insert(p_instance); - } - } - - if (p_instance->aabb.has_no_surface()) { - return; - } - - if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); - //make sure lights are updated if it casts shadow - - if (geom->can_cast_shadows) { - for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) { - InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); - light->shadow_dirty = true; - } - } - - if (!p_instance->lightmap && geom->lightmap_captures.size()) { - //affected by lightmap captures, must update capture info! - _update_instance_lightmap_captures(p_instance); - } else { - if (!p_instance->lightmap_sh.empty()) { - p_instance->lightmap_sh.clear(); //don't need SH - p_instance->lightmap_target_sh.clear(); //don't need SH - } - } - } - - if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) { - //if this moved, update the captured objects - InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data); - //erase dependencies, since no longer a lightmap - - for (List<InstanceLightmapData::PairInfo>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) { - Instance *geom = E->get().geometry; - _instance_queue_update(geom, true, false); - } - } - - p_instance->mirror = p_instance->transform.basis.determinant() < 0.0; - - AABB new_aabb; - - new_aabb = p_instance->transform.xform(p_instance->aabb); - - p_instance->transformed_aabb = new_aabb; - - if (!p_instance->scenario) { - return; - } - - if (p_instance->octree_id == 0) { - uint32_t base_type = 1 << p_instance->base_type; - uint32_t pairable_mask = 0; - bool pairable = false; - - if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL || p_instance->base_type == RS::INSTANCE_LIGHTMAP) { - pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0; - pairable = true; - } - - if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { - pairable_mask = p_instance->visible ? (1 << RS::INSTANCE_PARTICLES) : 0; - pairable = true; - } - - if (p_instance->base_type == RS::INSTANCE_GI_PROBE) { - //lights and geometries - pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT) : 0; - pairable = true; - } - - // not inside octree - p_instance->octree_id = p_instance->scenario->octree.create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask); - - } else { - /* - if (new_aabb==p_instance->data.transformed_aabb) - return; - */ - - p_instance->scenario->octree.move(p_instance->octree_id, new_aabb); - } -} - -void RenderingServerScene::_update_instance_aabb(Instance *p_instance) { - AABB new_aabb; - - ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_NONE && !p_instance->base.is_valid()); - - switch (p_instance->base_type) { - case RenderingServer::INSTANCE_NONE: { - // do nothing - } break; - case RenderingServer::INSTANCE_MESH: { - if (p_instance->custom_aabb) { - new_aabb = *p_instance->custom_aabb; - } else { - new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton); - } - - } break; - - case RenderingServer::INSTANCE_MULTIMESH: { - if (p_instance->custom_aabb) { - new_aabb = *p_instance->custom_aabb; - } else { - new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base); - } - - } break; - case RenderingServer::INSTANCE_IMMEDIATE: { - if (p_instance->custom_aabb) { - new_aabb = *p_instance->custom_aabb; - } else { - new_aabb = RSG::storage->immediate_get_aabb(p_instance->base); - } - - } break; - case RenderingServer::INSTANCE_PARTICLES: { - if (p_instance->custom_aabb) { - new_aabb = *p_instance->custom_aabb; - } else { - new_aabb = RSG::storage->particles_get_aabb(p_instance->base); - } - - } break; - case RenderingServer::INSTANCE_PARTICLES_COLLISION: { - new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base); - - } break; - case RenderingServer::INSTANCE_LIGHT: { - new_aabb = RSG::storage->light_get_aabb(p_instance->base); - - } break; - case RenderingServer::INSTANCE_REFLECTION_PROBE: { - new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base); - - } break; - case RenderingServer::INSTANCE_DECAL: { - new_aabb = RSG::storage->decal_get_aabb(p_instance->base); - - } break; - case RenderingServer::INSTANCE_GI_PROBE: { - new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base); - - } break; - case RenderingServer::INSTANCE_LIGHTMAP: { - new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base); - - } break; - default: { - } - } - - // <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs - if (p_instance->extra_margin) { - new_aabb.grow_by(p_instance->extra_margin); - } - - p_instance->aabb = new_aabb; -} - -void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instance) { - bool first_set = p_instance->lightmap_sh.size() == 0; - p_instance->lightmap_sh.resize(9); //using SH - p_instance->lightmap_target_sh.resize(9); //using SH - Color *instance_sh = p_instance->lightmap_target_sh.ptrw(); - bool inside = false; - Color accum_sh[9]; - float accum_blend = 0.0; - - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); - for (List<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { - Instance *lightmap = E->get(); - - bool interior = RSG::storage->lightmap_is_interior(lightmap->base); - - if (inside && !interior) { - continue; //we are inside, ignore exteriors - } - - Transform to_bounds = lightmap->transform.affine_inverse(); - Vector3 center = p_instance->transform.xform(p_instance->aabb.position + p_instance->aabb.size * 0.5); //use aabb center - - Vector3 lm_pos = to_bounds.xform(center); - - AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base); - if (!bounds.has_point(lm_pos)) { - continue; //not in this lightmap - } - - Color sh[9]; - RSG::storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh); - - //rotate it - Basis rot = lightmap->transform.basis.orthonormalized(); - for (int i = 0; i < 3; i++) { - float csh[9]; - for (int j = 0; j < 9; j++) { - csh[j] = sh[j][i]; - } - rot.rotate_sh(csh); - for (int j = 0; j < 9; j++) { - sh[j][i] = csh[j]; - } - } - - Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0); - - float blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z)); - //make blend more rounded - blend = Math::lerp(inner_pos.length(), blend, blend); - blend *= blend; - blend = MAX(0.0, 1.0 - blend); - - if (interior && !inside) { - //do not blend, just replace - for (int j = 0; j < 9; j++) { - accum_sh[j] = sh[j] * blend; - } - accum_blend = blend; - inside = true; - } else { - for (int j = 0; j < 9; j++) { - accum_sh[j] += sh[j] * blend; - } - accum_blend += blend; - } - } - - if (accum_blend > 0.0) { - for (int j = 0; j < 9; j++) { - instance_sh[j] = accum_sh[j] / accum_blend; - if (first_set) { - p_instance->lightmap_sh.write[j] = instance_sh[j]; - } - } - } -} - -bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario) { - InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); - - Transform light_transform = p_instance->transform; - light_transform.orthonormalize(); //scale does not count on lights - - bool animated_material_found = false; - - switch (RSG::storage->light_get_type(p_instance->base)) { - case RS::LIGHT_DIRECTIONAL: { - real_t max_distance = p_cam_projection.get_z_far(); - real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE); - if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera - max_distance = MIN(shadow_max, max_distance); - } - max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001); - real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance); - - RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base); - - real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE); - - if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) { - //optimize min/max - Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform); - int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); - Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2)); - //check distance max and min - - bool found_items = false; - real_t z_max = -1e20; - real_t z_min = 1e20; - - for (int i = 0; i < cull_count; i++) { - Instance *instance = instance_shadow_cull_result[i]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { - continue; - } - - if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { - animated_material_found = true; - } - - real_t max, min; - instance->transformed_aabb.project_range_in_plane(base, min, max); - - if (max > z_max) { - z_max = max; - } - - if (min < z_min) { - z_min = min; - } - - found_items = true; - } - - if (found_items) { - min_distance = MAX(min_distance, z_min); - max_distance = MIN(max_distance, z_max); - } - } - - real_t range = max_distance - min_distance; - - int splits = 0; - switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) { - case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: - splits = 1; - break; - case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: - splits = 2; - break; - case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: - splits = 4; - break; - } - - real_t distances[5]; - - distances[0] = min_distance; - for (int i = 0; i < splits; i++) { - distances[i + 1] = min_distance + RSG::storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range; - }; - - distances[splits] = max_distance; - - real_t texture_size = RSG::scene_render->get_directional_light_shadow_size(light->instance); - - bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base); - - real_t first_radius = 0.0; - - real_t min_distance_bias_scale = pancake_size > 0 ? distances[1] / 10.0 : 0; - - for (int i = 0; i < splits; i++) { - RENDER_TIMESTAMP("Culling Directional Light split" + itos(i)); - - // setup a camera matrix for that range! - CameraMatrix camera_matrix; - - real_t aspect = p_cam_projection.get_aspect(); - - if (p_cam_orthogonal) { - Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); - - camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); - } else { - real_t fov = p_cam_projection.get_fov(); //this is actually yfov, because set aspect tries to keep it - camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true); - } - - //obtain the frustum endpoints - - Vector3 endpoints[8]; // frustum plane endpoints - bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints); - ERR_CONTINUE(!res); - - // obtain the light frustm ranges (given endpoints) - - Transform transform = light_transform; //discard scale and stabilize light - - Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized(); - Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized(); - Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized(); - //z_vec points agsint the camera, like in default opengl - - real_t x_min = 0.f, x_max = 0.f; - real_t y_min = 0.f, y_max = 0.f; - real_t z_min = 0.f, z_max = 0.f; - - // FIXME: z_max_cam is defined, computed, but not used below when setting up - // ortho_camera. Commented out for now to fix warnings but should be investigated. - real_t x_min_cam = 0.f, x_max_cam = 0.f; - real_t y_min_cam = 0.f, y_max_cam = 0.f; - real_t z_min_cam = 0.f; - //real_t z_max_cam = 0.f; - - real_t bias_scale = 1.0; - real_t aspect_bias_scale = 1.0; - - //used for culling - - for (int j = 0; j < 8; j++) { - real_t d_x = x_vec.dot(endpoints[j]); - real_t d_y = y_vec.dot(endpoints[j]); - real_t d_z = z_vec.dot(endpoints[j]); - - if (j == 0 || d_x < x_min) { - x_min = d_x; - } - if (j == 0 || d_x > x_max) { - x_max = d_x; - } - - if (j == 0 || d_y < y_min) { - y_min = d_y; - } - if (j == 0 || d_y > y_max) { - y_max = d_y; - } - - if (j == 0 || d_z < z_min) { - z_min = d_z; - } - if (j == 0 || d_z > z_max) { - z_max = d_z; - } - } - - real_t radius = 0; - real_t soft_shadow_expand = 0; - Vector3 center; - - { - //camera viewport stuff - - for (int j = 0; j < 8; j++) { - center += endpoints[j]; - } - center /= 8.0; - - //center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5; - - for (int j = 0; j < 8; j++) { - real_t d = center.distance_to(endpoints[j]); - if (d > radius) { - radius = d; - } - } - - radius *= texture_size / (texture_size - 2.0); //add a texel by each side - - if (i == 0) { - first_radius = radius; - } else { - bias_scale = radius / first_radius; - } - - z_min_cam = z_vec.dot(center) - radius; - - { - float soft_shadow_angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE); - - if (soft_shadow_angle > 0.0 && pancake_size > 0.0) { - float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam; - soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range; - - x_max += soft_shadow_expand; - y_max += soft_shadow_expand; - - x_min -= soft_shadow_expand; - y_min -= soft_shadow_expand; - } - } - - x_max_cam = x_vec.dot(center) + radius + soft_shadow_expand; - x_min_cam = x_vec.dot(center) - radius - soft_shadow_expand; - y_max_cam = y_vec.dot(center) + radius + soft_shadow_expand; - y_min_cam = y_vec.dot(center) - radius - soft_shadow_expand; - - if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) { - //this trick here is what stabilizes the shadow (make potential jaggies to not move) - //at the cost of some wasted resolution. Still the quality increase is very well worth it - - real_t unit = radius * 2.0 / texture_size; - - x_max_cam = Math::stepify(x_max_cam, unit); - x_min_cam = Math::stepify(x_min_cam, unit); - y_max_cam = Math::stepify(y_max_cam, unit); - y_min_cam = Math::stepify(y_min_cam, unit); - } - } - - //now that we now all ranges, we can proceed to make the light frustum planes, for culling octree - - Vector<Plane> light_frustum_planes; - light_frustum_planes.resize(6); - - //right/left - light_frustum_planes.write[0] = Plane(x_vec, x_max); - light_frustum_planes.write[1] = Plane(-x_vec, -x_min); - //top/bottom - light_frustum_planes.write[2] = Plane(y_vec, y_max); - light_frustum_planes.write[3] = Plane(-y_vec, -y_min); - //near/far - light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6); - light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed - - int cull_count = p_scenario->octree.cull_convex(light_frustum_planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); - - // a pre pass will need to be needed to determine the actual z-near to be used - - Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); - - real_t cull_max = 0; - for (int j = 0; j < cull_count; j++) { - real_t min, max; - Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { - cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); - j--; - continue; - } - - instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max); - instance->depth = near_plane.distance_to(instance->transform.origin); - instance->depth_layer = 0; - if (j == 0 || max > cull_max) { - cull_max = max; - } - } - - if (cull_max > z_max) { - z_max = cull_max; - } - - if (pancake_size > 0) { - z_max = z_vec.dot(center) + radius + pancake_size; - } - - if (aspect != 1.0) { - // if the aspect is different, then the radius will become larger. - // if this happens, then bias needs to be adjusted too, as depth will increase - // to do this, compare the depth of one that would have resulted from a square frustum - - CameraMatrix camera_matrix_square; - if (p_cam_orthogonal) { - Vector2 vp_he = camera_matrix.get_viewport_half_extents(); - if (p_cam_vaspect) { - camera_matrix_square.set_orthogonal(vp_he.x * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true); - } else { - camera_matrix_square.set_orthogonal(vp_he.y * 2.0, 1.0, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); - } - } else { - Vector2 vp_he = camera_matrix.get_viewport_half_extents(); - if (p_cam_vaspect) { - camera_matrix_square.set_frustum(vp_he.x * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], true); - } else { - camera_matrix_square.set_frustum(vp_he.y * 2.0, 1.0, Vector2(), distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); - } - } - - Vector3 endpoints_square[8]; // frustum plane endpoints - res = camera_matrix_square.get_endpoints(p_cam_transform, endpoints_square); - ERR_CONTINUE(!res); - Vector3 center_square; - real_t z_max_square = 0; - - for (int j = 0; j < 8; j++) { - center_square += endpoints_square[j]; - - real_t d_z = z_vec.dot(endpoints_square[j]); - - if (j == 0 || d_z > z_max_square) { - z_max_square = d_z; - } - } - - if (cull_max > z_max_square) { - z_max_square = cull_max; - } - - center_square /= 8.0; - - real_t radius_square = 0; - - for (int j = 0; j < 8; j++) { - real_t d = center_square.distance_to(endpoints_square[j]); - if (d > radius_square) { - radius_square = d; - } - } - - radius_square *= texture_size / (texture_size - 2.0); //add a texel by each side - - if (pancake_size > 0) { - z_max_square = z_vec.dot(center_square) + radius_square + pancake_size; - } - - real_t z_min_cam_square = z_vec.dot(center_square) - radius_square; - - aspect_bias_scale = (z_max - z_min_cam) / (z_max_square - z_min_cam_square); - - // this is not entirely perfect, because the cull-adjusted z-max may be different - // but at least it's warranted that it results in a greater bias, so no acne should be present either way. - // pancaking also helps with this. - } - - { - CameraMatrix ortho_camera; - real_t half_x = (x_max_cam - x_min_cam) * 0.5; - real_t half_y = (y_max_cam - y_min_cam) * 0.5; - - ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam)); - - Vector2 uv_scale(1.0 / (x_max_cam - x_min_cam), 1.0 / (y_max_cam - y_min_cam)); - - Transform ortho_transform; - ortho_transform.basis = transform.basis; - ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max; - - { - Vector3 max_in_view = p_cam_transform.affine_inverse().xform(z_vec * cull_max); - Vector3 dir_in_view = p_cam_transform.xform_inv(z_vec).normalized(); - cull_max = dir_in_view.dot(max_in_view); - } - - RSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, z_max - z_min_cam, distances[i + 1], i, radius * 2.0 / texture_size, bias_scale * aspect_bias_scale * min_distance_bias_scale, z_max, uv_scale); - } - - RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); - } - - } break; - case RS::LIGHT_OMNI: { - RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base); - - if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::scene_render->light_instances_can_render_shadow_cube()) { - for (int i = 0; i < 2; i++) { - //using this one ensures that raster deferred will have it - RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i)); - - real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); - - real_t z = i == 0 ? -1 : 1; - Vector<Plane> planes; - planes.resize(6); - planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius)); - planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius)); - planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius)); - planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius)); - planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius)); - planes.write[5] = light_transform.xform(Plane(Vector3(0, 0, -z), 0)); - - int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); - Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z); - - for (int j = 0; j < cull_count; j++) { - Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { - cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); - j--; - } else { - if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { - animated_material_found = true; - } - - instance->depth = near_plane.distance_to(instance->transform.origin); - instance->depth_layer = 0; - } - } - - RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0); - RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); - } - } else { //shadow cube - - real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); - CameraMatrix cm; - cm.set_perspective(90, 1, 0.01, radius); - - for (int i = 0; i < 6; i++) { - RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i)); - //using this one ensures that raster deferred will have it - - static const Vector3 view_normals[6] = { - Vector3(+1, 0, 0), - Vector3(-1, 0, 0), - Vector3(0, -1, 0), - Vector3(0, +1, 0), - Vector3(0, 0, +1), - Vector3(0, 0, -1) - }; - static const Vector3 view_up[6] = { - Vector3(0, -1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, -1), - Vector3(0, 0, +1), - Vector3(0, -1, 0), - Vector3(0, -1, 0) - }; - - Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]); - - Vector<Plane> planes = cm.get_projection_planes(xform); - - int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); - - Plane near_plane(xform.origin, -xform.basis.get_axis(2)); - for (int j = 0; j < cull_count; j++) { - Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { - cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); - j--; - } else { - if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { - animated_material_found = true; - } - instance->depth = near_plane.distance_to(instance->transform.origin); - instance->depth_layer = 0; - } - } - - RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0); - RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); - } - - //restore the regular DP matrix - RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0); - } - - } break; - case RS::LIGHT_SPOT: { - RENDER_TIMESTAMP("Culling Spot Light"); - - real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); - real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); - - CameraMatrix cm; - cm.set_perspective(angle * 2.0, 1.0, 0.01, radius); - - Vector<Plane> planes = cm.get_projection_planes(light_transform); - int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); - - Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); - for (int j = 0; j < cull_count; j++) { - Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) { - cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); - j--; - } else { - if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) { - animated_material_found = true; - } - instance->depth = near_plane.distance_to(instance->transform.origin); - instance->depth_layer = 0; - } - } - - RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0); - RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); - - } break; - } - - return animated_material_found; -} - -void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) { -// render to mono camera -#ifndef _3D_DISABLED - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - - /* STEP 1 - SETUP CAMERA */ - CameraMatrix camera_matrix; - bool ortho = false; - - switch (camera->type) { - case Camera::ORTHOGONAL: { - camera_matrix.set_orthogonal( - camera->size, - p_viewport_size.width / (float)p_viewport_size.height, - camera->znear, - camera->zfar, - camera->vaspect); - ortho = true; - } break; - case Camera::PERSPECTIVE: { - camera_matrix.set_perspective( - camera->fov, - p_viewport_size.width / (float)p_viewport_size.height, - camera->znear, - camera->zfar, - camera->vaspect); - ortho = false; - - } break; - case Camera::FRUSTUM: { - camera_matrix.set_frustum( - camera->size, - p_viewport_size.width / (float)p_viewport_size.height, - camera->offset, - camera->znear, - camera->zfar, - camera->vaspect); - ortho = false; - } break; - } - - RID environment = _render_get_environment(p_camera, p_scenario); - - _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); - _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); -#endif -} - -void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) { - // render for AR/VR interface - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - - /* SETUP CAMERA, we are ignoring type and FOV here */ - float aspect = p_viewport_size.width / (float)p_viewport_size.height; - CameraMatrix camera_matrix = p_interface->get_projection_for_eye(p_eye, aspect, camera->znear, camera->zfar); - - // We also ignore our camera position, it will have been positioned with a slightly old tracking position. - // Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo! - Transform world_origin = XRServer::get_singleton()->get_world_origin(); - Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin); - - RID environment = _render_get_environment(p_camera, p_scenario); - - // For stereo render we only prepare for our left eye and then reuse the outcome for our right eye - if (p_eye == XRInterface::EYE_LEFT) { - // Center our transform, we assume basis is equal. - Transform mono_transform = cam_transform; - Transform right_transform = p_interface->get_transform_for_eye(XRInterface::EYE_RIGHT, world_origin); - mono_transform.origin += right_transform.origin; - mono_transform.origin *= 0.5; - - // We need to combine our projection frustums for culling. - // Ideally we should use our clipping planes for this and combine them, - // however our shadow map logic uses our projection matrix. - // Note: as our left and right frustums should be mirrored, we don't need our right projection matrix. - - // - get some base values we need - float eye_dist = (mono_transform.origin - cam_transform.origin).length(); - float z_near = camera_matrix.get_z_near(); // get our near plane - float z_far = camera_matrix.get_z_far(); // get our far plane - float width = (2.0 * z_near) / camera_matrix.matrix[0][0]; - float x_shift = width * camera_matrix.matrix[2][0]; - float height = (2.0 * z_near) / camera_matrix.matrix[1][1]; - float y_shift = height * camera_matrix.matrix[2][1]; - - // printf("Eye_dist = %f, Near = %f, Far = %f, Width = %f, Shift = %f\n", eye_dist, z_near, z_far, width, x_shift); - - // - calculate our near plane size (horizontal only, right_near is mirrored) - float left_near = -eye_dist - ((width - x_shift) * 0.5); - - // - calculate our far plane size (horizontal only, right_far is mirrored) - float left_far = -eye_dist - (z_far * (width - x_shift) * 0.5 / z_near); - float left_far_right_eye = eye_dist - (z_far * (width + x_shift) * 0.5 / z_near); - if (left_far > left_far_right_eye) { - // on displays smaller then double our iod, the right eye far frustrum can overtake the left eyes. - left_far = left_far_right_eye; - } - - // - figure out required z-shift - float slope = (left_far - left_near) / (z_far - z_near); - float z_shift = (left_near / slope) - z_near; - - // - figure out new vertical near plane size (this will be slightly oversized thanks to our z-shift) - float top_near = (height - y_shift) * 0.5; - top_near += (top_near / z_near) * z_shift; - float bottom_near = -(height + y_shift) * 0.5; - bottom_near += (bottom_near / z_near) * z_shift; - - // printf("Left_near = %f, Left_far = %f, Top_near = %f, Bottom_near = %f, Z_shift = %f\n", left_near, left_far, top_near, bottom_near, z_shift); - - // - generate our frustum - CameraMatrix combined_matrix; - combined_matrix.set_frustum(left_near, -left_near, bottom_near, top_near, z_near + z_shift, z_far + z_shift); - - // and finally move our camera back - Transform apply_z_shift; - apply_z_shift.origin = Vector3(0.0, 0.0, z_shift); // z negative is forward so this moves it backwards - mono_transform *= apply_z_shift; - - // now prepare our scene with our adjusted transform projection matrix - _prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); - } else if (p_eye == XRInterface::EYE_MONO) { - // For mono render, prepare as per usual - _prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); - } - - // And render our scene... - _render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); -}; - -void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) { - // Note, in stereo rendering: - // - p_cam_transform will be a transform in the middle of our two eyes - // - p_cam_projection is a wider frustrum that encompasses both eyes - - Scenario *scenario = scenario_owner.getornull(p_scenario); - - render_pass++; - uint32_t camera_layer_mask = p_visible_layers; - - RSG::scene_render->set_scene_pass(render_pass); - - if (p_render_buffers.is_valid()) { - RSG::scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not) - } - - RENDER_TIMESTAMP("Frustum Culling"); - - //rasterizer->set_camera(camera->transform, camera_matrix,ortho); - - Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform); - - Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized()); - float z_far = p_cam_projection.get_z_far(); - - /* STEP 2 - CULL */ - instance_cull_count = scenario->octree.cull_convex(planes, instance_cull_result, MAX_INSTANCE_CULL); - light_cull_count = 0; - - reflection_probe_cull_count = 0; - decal_cull_count = 0; - gi_probe_cull_count = 0; - lightmap_cull_count = 0; - - //light_samplers_culled=0; - - /* - print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); - print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); - print_line("OTE: "+itos(p_scenario->octree.get_elem_count())); - print_line("OTP: "+itos(p_scenario->octree.get_pair_count())); - */ - - /* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */ - //removed, will replace with culling - - /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */ - uint64_t frame_number = RSG::rasterizer->get_frame_number(); - float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time(); - - for (int i = 0; i < instance_cull_count; i++) { - Instance *ins = instance_cull_result[i]; - - bool keep = false; - - if ((camera_layer_mask & ins->layer_mask) == 0) { - //failure - } else if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) { - if (light_cull_count < MAX_LIGHTS_CULLED) { - InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data); - - if (!light->geometries.empty()) { - //do not add this light if no geometry is affected by it.. - light_cull_result[light_cull_count] = ins; - light_instance_cull_result[light_cull_count] = light->instance; - if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(ins->base)) { - RSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later - } - - light_cull_count++; - } - } - } else if (ins->base_type == RS::INSTANCE_REFLECTION_PROBE && ins->visible) { - if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) { - InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data); - - if (p_reflection_probe != reflection_probe->instance) { - //avoid entering The Matrix - - if (!reflection_probe->geometries.empty()) { - //do not add this light if no geometry is affected by it.. - - if (reflection_probe->reflection_dirty || RSG::scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) { - if (!reflection_probe->update_list.in_list()) { - reflection_probe->render_step = 0; - reflection_probe_render_list.add_last(&reflection_probe->update_list); - } - - reflection_probe->reflection_dirty = false; - } - - if (RSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) { - reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance; - reflection_probe_cull_count++; - } - } - } - } - } else if (ins->base_type == RS::INSTANCE_DECAL && ins->visible) { - if (decal_cull_count < MAX_DECALS_CULLED) { - InstanceDecalData *decal = static_cast<InstanceDecalData *>(ins->base_data); - - if (!decal->geometries.empty()) { - //do not add this decal if no geometry is affected by it.. - decal_instance_cull_result[decal_cull_count] = decal->instance; - decal_cull_count++; - } - } - - } else if (ins->base_type == RS::INSTANCE_GI_PROBE && ins->visible) { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(ins->base_data); - if (!gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - - if (gi_probe_cull_count < MAX_GI_PROBES_CULLED) { - gi_probe_instance_cull_result[gi_probe_cull_count] = gi_probe->probe_instance; - gi_probe_cull_count++; - } - } else if (ins->base_type == RS::INSTANCE_LIGHTMAP && ins->visible) { - if (lightmap_cull_count < MAX_LIGHTMAPS_CULLED) { - lightmap_cull_result[lightmap_cull_count] = ins; - lightmap_cull_count++; - } - - } else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { - keep = true; - - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data); - - if (ins->redraw_if_visible) { - RenderingServerRaster::redraw_request(); - } - - if (ins->base_type == RS::INSTANCE_PARTICLES) { - //particles visible? process them - if (RSG::storage->particles_is_inactive(ins->base)) { - //but if nothing is going on, don't do it. - keep = false; - } else { - RSG::storage->particles_request_process(ins->base); - RSG::storage->particles_set_view_axis(ins->base, -p_cam_transform.basis.get_axis(2).normalized()); - //particles visible? request redraw - RenderingServerRaster::redraw_request(); - } - } - - if (geom->lighting_dirty) { - int l = 0; - //only called when lights AABB enter/exit this geometry - ins->light_instances.resize(geom->lighting.size()); - - for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) { - InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); - - ins->light_instances.write[l++] = light->instance; - } - - geom->lighting_dirty = false; - } - - if (geom->reflection_dirty) { - int l = 0; - //only called when reflection probe AABB enter/exit this geometry - ins->reflection_probe_instances.resize(geom->reflection_probes.size()); - - for (List<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) { - InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data); - - ins->reflection_probe_instances.write[l++] = reflection_probe->instance; - } - - geom->reflection_dirty = false; - } - - if (geom->gi_probes_dirty) { - int l = 0; - //only called when reflection probe AABB enter/exit this geometry - ins->gi_probe_instances.resize(geom->gi_probes.size()); - - for (List<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) { - InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data); - - ins->gi_probe_instances.write[l++] = gi_probe->probe_instance; - } - - geom->gi_probes_dirty = false; - } - - if (ins->last_frame_pass != frame_number && !ins->lightmap_target_sh.empty() && !ins->lightmap_sh.empty()) { - Color *sh = ins->lightmap_sh.ptrw(); - const Color *target_sh = ins->lightmap_target_sh.ptr(); - for (uint32_t j = 0; j < 9; j++) { - sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed)); - } - } - - ins->depth = near_plane.distance_to(ins->transform.origin); - ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15); - } - - if (!keep) { - // remove, no reason to keep - instance_cull_count--; - SWAP(instance_cull_result[i], instance_cull_result[instance_cull_count]); - i--; - ins->last_render_pass = 0; // make invalid - } else { - ins->last_render_pass = render_pass; - } - ins->last_frame_pass = frame_number; - } - - /* STEP 5 - PROCESS LIGHTS */ - - RID *directional_light_ptr = &light_instance_cull_result[light_cull_count]; - directional_light_count = 0; - - // directional lights - { - Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size()); - int directional_shadow_count = 0; - - for (List<Instance *>::Element *E = scenario->directional_lights.front(); E; E = E->next()) { - if (light_cull_count + directional_light_count >= MAX_LIGHTS_CULLED) { - break; - } - - if (!E->get()->visible) { - continue; - } - - InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); - - //check shadow.. - - if (light) { - if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base)) { - lights_with_shadow[directional_shadow_count++] = E->get(); - } - //add to list - directional_light_ptr[directional_light_count++] = light->instance; - } - } - - RSG::scene_render->set_directional_shadow_count(directional_shadow_count); - - for (int i = 0; i < directional_shadow_count; i++) { - RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i)); - - _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario); - - RENDER_TIMESTAMP("<Rendering Directional Light " + itos(i)); - } - } - - if (p_using_shadows) { //setup shadow maps - - //SortArray<Instance*,_InstanceLightsort> sorter; - //sorter.sort(light_cull_result,light_cull_count); - for (int i = 0; i < light_cull_count; i++) { - Instance *ins = light_cull_result[i]; - - if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) { - continue; - } - - InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data); - - float coverage = 0.f; - - { //compute coverage - - Transform cam_xf = p_cam_transform; - float zn = p_cam_projection.get_z_near(); - Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane - - // near plane half width and height - Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents(); - - switch (RSG::storage->light_get_type(ins->base)) { - case RS::LIGHT_OMNI: { - float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE); - - //get two points parallel to near plane - Vector3 points[2] = { - ins->transform.origin, - ins->transform.origin + cam_xf.basis.get_axis(0) * radius - }; - - if (!p_cam_orthogonal) { - //if using perspetive, map them to near plane - for (int j = 0; j < 2; j++) { - if (p.distance_to(points[j]) < 0) { - points[j].z = -zn; //small hack to keep size constant when hitting the screen - } - - p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane - } - } - - float screen_diameter = points[0].distance_to(points[1]) * 2; - coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y); - } break; - case RS::LIGHT_SPOT: { - float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE); - float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE); - - float w = radius * Math::sin(Math::deg2rad(angle)); - float d = radius * Math::cos(Math::deg2rad(angle)); - - Vector3 base = ins->transform.origin - ins->transform.basis.get_axis(2).normalized() * d; - - Vector3 points[2] = { - base, - base + cam_xf.basis.get_axis(0) * w - }; - - if (!p_cam_orthogonal) { - //if using perspetive, map them to near plane - for (int j = 0; j < 2; j++) { - if (p.distance_to(points[j]) < 0) { - points[j].z = -zn; //small hack to keep size constant when hitting the screen - } - - p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane - } - } - - float screen_diameter = points[0].distance_to(points[1]) * 2; - coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y); - - } break; - default: { - ERR_PRINT("Invalid Light Type"); - } - } - } - - if (light->shadow_dirty) { - light->last_version++; - light->shadow_dirty = false; - } - - bool redraw = RSG::scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version); - - if (redraw) { - //must redraw! - RENDER_TIMESTAMP(">Rendering Light " + itos(i)); - light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_cam_vaspect, p_shadow_atlas, scenario); - RENDER_TIMESTAMP("<Rendering Light " + itos(i)); - } - } - } - - /* UPDATE SDFGI */ - - if (p_render_buffers.is_valid()) { - uint32_t cascade_index[8]; - uint32_t cascade_sizes[8]; - const RID *cascade_ptrs[8]; - uint32_t cascade_count = 0; - uint32_t sdfgi_light_cull_count = 0; - - uint32_t prev_cascade = 0xFFFFFFFF; - for (int i = 0; i < RSG::scene_render->sdfgi_get_pending_region_count(p_render_buffers); i++) { - AABB region = RSG::scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i); - uint32_t region_cascade = RSG::scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i); - - if (region_cascade != prev_cascade) { - cascade_sizes[cascade_count] = 0; - cascade_index[cascade_count] = region_cascade; - cascade_ptrs[cascade_count] = &sdfgi_light_cull_result[sdfgi_light_cull_count]; - cascade_count++; - sdfgi_light_cull_pass++; - prev_cascade = region_cascade; - } - uint32_t sdfgi_cull_count = scenario->octree.cull_aabb(region, instance_shadow_cull_result, MAX_INSTANCE_CULL); - - for (uint32_t j = 0; j < sdfgi_cull_count; j++) { - Instance *ins = instance_shadow_cull_result[j]; - - bool keep = false; - - if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) { - InstanceLightData *instance_light = (InstanceLightData *)ins->base_data; - if (instance_light->bake_mode != RS::LIGHT_BAKE_STATIC || region_cascade > instance_light->max_sdfgi_cascade) { - continue; - } - - if (sdfgi_light_cull_pass != instance_light->sdfgi_cascade_light_pass && sdfgi_light_cull_count < MAX_LIGHTS_CULLED) { - instance_light->sdfgi_cascade_light_pass = sdfgi_light_cull_pass; - sdfgi_light_cull_result[sdfgi_light_cull_count++] = instance_light->instance; - cascade_sizes[cascade_count - 1]++; - } - } else if ((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) { - if (ins->baked_light) { - keep = true; - } - } - - if (!keep) { - // remove, no reason to keep - sdfgi_cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[sdfgi_cull_count]); - j--; - } - } - - RSG::scene_render->render_sdfgi(p_render_buffers, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, sdfgi_cull_count); - //have to save updated cascades, then update static lights. - } - - if (sdfgi_light_cull_count) { - RSG::scene_render->render_sdfgi_static_lights(p_render_buffers, cascade_count, cascade_index, cascade_ptrs, cascade_sizes); - } - - RSG::scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_light_ptr, directional_light_count, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size()); - } -} - -RID RenderingServerScene::_render_get_environment(RID p_camera, RID p_scenario) { - Camera *camera = camera_owner.getornull(p_camera); - if (camera && RSG::scene_render->is_environment(camera->env)) { - return camera->env; - } - - Scenario *scenario = scenario_owner.getornull(p_scenario); - if (!scenario) { - return RID(); - } - if (RSG::scene_render->is_environment(scenario->environment)) { - return scenario->environment; - } - - if (RSG::scene_render->is_environment(scenario->fallback_environment)) { - return scenario->fallback_environment; - } - - return RID(); -} - -void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { - Scenario *scenario = scenario_owner.getornull(p_scenario); - - RID camera_effects; - if (p_force_camera_effects.is_valid()) { - camera_effects = p_force_camera_effects; - } else { - camera_effects = scenario->camera_effects; - } - /* PROCESS GEOMETRY AND DRAW SCENE */ - - RENDER_TIMESTAMP("Render Scene "); - RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); -} - -void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) { -#ifndef _3D_DISABLED - - Scenario *scenario = scenario_owner.getornull(p_scenario); - - RID environment; - if (scenario->environment.is_valid()) { - environment = scenario->environment; - } else { - environment = scenario->fallback_environment; - } - RENDER_TIMESTAMP("Render Empty Scene "); - RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0); -#endif -} - -bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, int p_step) { - InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data); - Scenario *scenario = p_instance->scenario; - ERR_FAIL_COND_V(!scenario, true); - - RenderingServerRaster::redraw_request(); //update, so it updates in editor - - if (p_step == 0) { - if (!RSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) { - return true; //all full - } - } - - if (p_step >= 0 && p_step < 6) { - static const Vector3 view_normals[6] = { - Vector3(+1, 0, 0), - Vector3(-1, 0, 0), - Vector3(0, +1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, +1), - Vector3(0, 0, -1) - }; - static const Vector3 view_up[6] = { - Vector3(0, -1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, +1), - Vector3(0, 0, -1), - Vector3(0, -1, 0), - Vector3(0, -1, 0) - }; - - Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base); - Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base); - float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base); - - Vector3 edge = view_normals[p_step] * extents; - float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit - - max_distance = MAX(max_distance, distance); - - //render cubemap side - CameraMatrix cm; - cm.set_perspective(90, 1, 0.01, max_distance); - - Transform local_view; - local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]); - - Transform xform = p_instance->transform * local_view; - - RID shadow_atlas; - - bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base); - if (use_shadows) { - shadow_atlas = scenario->reflection_probe_shadow_atlas; - } - - RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step)); - _prepare_scene(xform, cm, false, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows); - _render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step); - - } else { - //do roughness postprocess step until it believes it's done - RENDER_TIMESTAMP("Post-Process Reflection Probe, Step " + itos(p_step)); - return RSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); - } - - return false; -} - -void RenderingServerScene::render_probes() { - /* REFLECTION PROBES */ - - SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first(); - - bool busy = false; - - while (ref_probe) { - SelfList<InstanceReflectionProbeData> *next = ref_probe->next(); - RID base = ref_probe->self()->owner->base; - - switch (RSG::storage->reflection_probe_get_update_mode(base)) { - case RS::REFLECTION_PROBE_UPDATE_ONCE: { - if (busy) { //already rendering something - break; - } - - bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step); - if (done) { - reflection_probe_render_list.remove(ref_probe); - } else { - ref_probe->self()->render_step++; - } - - busy = true; //do not render another one of this kind - } break; - case RS::REFLECTION_PROBE_UPDATE_ALWAYS: { - int step = 0; - bool done = false; - while (!done) { - done = _render_reflection_probe_step(ref_probe->self()->owner, step); - step++; - } - - reflection_probe_render_list.remove(ref_probe); - } break; - } - - ref_probe = next; - } - - /* GI PROBES */ - - SelfList<InstanceGIProbeData> *gi_probe = gi_probe_update_list.first(); - - if (gi_probe) { - RENDER_TIMESTAMP("Render GI Probes"); - } - - while (gi_probe) { - SelfList<InstanceGIProbeData> *next = gi_probe->next(); - - InstanceGIProbeData *probe = gi_probe->self(); - //Instance *instance_probe = probe->owner; - - //check if probe must be setup, but don't do if on the lighting thread - - bool cache_dirty = false; - int cache_count = 0; - { - int light_cache_size = probe->light_cache.size(); - const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr(); - const RID *instance_caches = probe->light_instances.ptr(); - - int idx = 0; //must count visible lights - for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { - Instance *instance = E->get(); - InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; - if (!instance->visible) { - continue; - } - if (cache_dirty) { - //do nothing, since idx must count all visible lights anyway - } else if (idx >= light_cache_size) { - cache_dirty = true; - } else { - const InstanceGIProbeData::LightCache *cache = &caches[idx]; - - if ( - instance_caches[idx] != instance_light->instance || - cache->has_shadow != RSG::storage->light_has_shadow(instance->base) || - cache->type != RSG::storage->light_get_type(instance->base) || - cache->transform != instance->transform || - cache->color != RSG::storage->light_get_color(instance->base) || - cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) || - cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) || - cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) || - cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) || - cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) || - cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) { - cache_dirty = true; - } - } - - idx++; - } - - for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) { - Instance *instance = E->get(); - InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; - if (!instance->visible) { - continue; - } - if (cache_dirty) { - //do nothing, since idx must count all visible lights anyway - } else if (idx >= light_cache_size) { - cache_dirty = true; - } else { - const InstanceGIProbeData::LightCache *cache = &caches[idx]; - - if ( - instance_caches[idx] != instance_light->instance || - cache->has_shadow != RSG::storage->light_has_shadow(instance->base) || - cache->type != RSG::storage->light_get_type(instance->base) || - cache->transform != instance->transform || - cache->color != RSG::storage->light_get_color(instance->base) || - cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) || - cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) || - cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) || - cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) || - cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) || - cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) { - cache_dirty = true; - } - } - - idx++; - } - - if (idx != light_cache_size) { - cache_dirty = true; - } - - cache_count = idx; - } - - bool update_lights = RSG::scene_render->gi_probe_needs_update(probe->probe_instance); - - if (cache_dirty) { - probe->light_cache.resize(cache_count); - probe->light_instances.resize(cache_count); - - if (cache_count) { - InstanceGIProbeData::LightCache *caches = probe->light_cache.ptrw(); - RID *instance_caches = probe->light_instances.ptrw(); - - int idx = 0; //must count visible lights - for (Set<Instance *>::Element *E = probe->lights.front(); E; E = E->next()) { - Instance *instance = E->get(); - InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; - if (!instance->visible) { - continue; - } - - InstanceGIProbeData::LightCache *cache = &caches[idx]; - - instance_caches[idx] = instance_light->instance; - cache->has_shadow = RSG::storage->light_has_shadow(instance->base); - cache->type = RSG::storage->light_get_type(instance->base); - cache->transform = instance->transform; - cache->color = RSG::storage->light_get_color(instance->base); - cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY); - cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY); - cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE); - cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION); - cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); - cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION); - - idx++; - } - for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) { - Instance *instance = E->get(); - InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; - if (!instance->visible) { - continue; - } - - InstanceGIProbeData::LightCache *cache = &caches[idx]; - - instance_caches[idx] = instance_light->instance; - cache->has_shadow = RSG::storage->light_has_shadow(instance->base); - cache->type = RSG::storage->light_get_type(instance->base); - cache->transform = instance->transform; - cache->color = RSG::storage->light_get_color(instance->base); - cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY); - cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY); - cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE); - cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION); - cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); - cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION); - - idx++; - } - } - - update_lights = true; - } - - instance_cull_count = 0; - for (List<InstanceGIProbeData::PairInfo>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) { - if (instance_cull_count < MAX_INSTANCE_CULL) { - Instance *ins = E->get().geometry; - if (!ins->visible) { - continue; - } - InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data; - - if (geom->gi_probes_dirty) { - //giprobes may be dirty, so update - int l = 0; - //only called when reflection probe AABB enter/exit this geometry - ins->gi_probe_instances.resize(geom->gi_probes.size()); - - for (List<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) { - InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data); - - ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance; - } - - geom->gi_probes_dirty = false; - } - - instance_cull_result[instance_cull_count++] = E->get().geometry; - } - } - - RSG::scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, instance_cull_count, (RasterizerScene::InstanceBase **)instance_cull_result); - - gi_probe_update_list.remove(gi_probe); - - gi_probe = next; - } -} - -void RenderingServerScene::render_particle_colliders() { - while (heightfield_particle_colliders_update_list.front()) { - Instance *hfpc = heightfield_particle_colliders_update_list.front()->get(); - - if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) { - //update heightfield - int cull_count = hfpc->scenario->octree.cull_aabb(hfpc->transformed_aabb, instance_cull_result, MAX_INSTANCE_CULL); //@TODO: cull mask missing - for (int i = 0; i < cull_count; i++) { - Instance *instance = instance_cull_result[i]; - if (!instance->visible || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision - cull_count--; - SWAP(instance_cull_result[i], instance_cull_result[cull_count]); - } - } - - RSG::scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, (RasterizerScene::InstanceBase **)instance_cull_result, cull_count); - } - heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front()); - } -} - -void RenderingServerScene::_update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material) { - List<RasterizerStorage::InstanceShaderParam> plist; - RSG::storage->material_get_instance_shader_parameters(p_material, &plist); - for (List<RasterizerStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) { - StringName name = E->get().info.name; - if (isparams.has(name)) { - if (isparams[name].info.type != E->get().info.type) { - WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different data types. Only the first one (in order) will display correctly."); - } - if (isparams[name].index != E->get().index) { - WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different indices. Only the first one (in order) will display correctly."); - } - continue; //first one found always has priority - } - - RasterizerScene::InstanceBase::InstanceShaderParameter isp; - isp.index = E->get().index; - isp.info = E->get().info; - isp.default_value = E->get().default_value; - if (existing_isparams.has(name)) { - isp.value = existing_isparams[name].value; - } else { - isp.value = E->get().default_value; - } - isparams[name] = isp; - } -} - -void RenderingServerScene::_update_dirty_instance(Instance *p_instance) { - if (p_instance->update_aabb) { - _update_instance_aabb(p_instance); - } - - if (p_instance->update_dependencies) { - p_instance->instance_increase_version(); - - if (p_instance->base.is_valid()) { - RSG::storage->base_update_dependency(p_instance->base, p_instance); - } - - if (p_instance->material_override.is_valid()) { - RSG::storage->material_update_dependency(p_instance->material_override, p_instance); - } - - if (p_instance->base_type == RS::INSTANCE_MESH) { - //remove materials no longer used and un-own them - - int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base); - p_instance->materials.resize(new_mat_count); - - int new_blend_shape_count = RSG::storage->mesh_get_blend_shape_count(p_instance->base); - if (new_blend_shape_count != p_instance->blend_values.size()) { - p_instance->blend_values.resize(new_blend_shape_count); - for (int i = 0; i < new_blend_shape_count; i++) { - p_instance->blend_values.write[i] = 0; - } - } - } - - if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { - InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data); - - bool can_cast_shadows = true; - bool is_animated = false; - Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> isparams; - - if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) { - can_cast_shadows = false; - } - - if (p_instance->material_override.is_valid()) { - if (!RSG::storage->material_casts_shadows(p_instance->material_override)) { - can_cast_shadows = false; - } - is_animated = RSG::storage->material_is_animated(p_instance->material_override); - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override); - } else { - if (p_instance->base_type == RS::INSTANCE_MESH) { - RID mesh = p_instance->base; - - if (mesh.is_valid()) { - bool cast_shadows = false; - - for (int i = 0; i < p_instance->materials.size(); i++) { - RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i); - - if (!mat.is_valid()) { - cast_shadows = true; - } else { - if (RSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - - if (RSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - - RSG::storage->material_update_dependency(mat, p_instance); - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - } - - } else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) { - RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base); - if (mesh.is_valid()) { - bool cast_shadows = false; - - int sc = RSG::storage->mesh_get_surface_count(mesh); - for (int i = 0; i < sc; i++) { - RID mat = RSG::storage->mesh_surface_get_material(mesh, i); - - if (!mat.is_valid()) { - cast_shadows = true; - - } else { - if (RSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - if (RSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - - RSG::storage->material_update_dependency(mat, p_instance); - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - - RSG::storage->base_update_dependency(mesh, p_instance); - } - } else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) { - RID mat = RSG::storage->immediate_get_material(p_instance->base); - - if (!(!mat.is_valid() || RSG::storage->material_casts_shadows(mat))) { - can_cast_shadows = false; - } - - if (mat.is_valid() && RSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - if (mat.is_valid()) { - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - } - - if (mat.is_valid()) { - RSG::storage->material_update_dependency(mat, p_instance); - } - - } else if (p_instance->base_type == RS::INSTANCE_PARTICLES) { - bool cast_shadows = false; - - int dp = RSG::storage->particles_get_draw_passes(p_instance->base); - - for (int i = 0; i < dp; i++) { - RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i); - if (!mesh.is_valid()) { - continue; - } - - int sc = RSG::storage->mesh_get_surface_count(mesh); - for (int j = 0; j < sc; j++) { - RID mat = RSG::storage->mesh_surface_get_material(mesh, j); - - if (!mat.is_valid()) { - cast_shadows = true; - } else { - if (RSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - - if (RSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat); - - RSG::storage->material_update_dependency(mat, p_instance); - } - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - } - } - - if (can_cast_shadows != geom->can_cast_shadows) { - //ability to cast shadows change, let lights now - for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) { - InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data); - light->shadow_dirty = true; - } - - geom->can_cast_shadows = can_cast_shadows; - } - - geom->material_is_animated = is_animated; - p_instance->instance_shader_parameters = isparams; - - if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) { - p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0); - if (p_instance->instance_allocated_shader_parameters) { - p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self); - for (Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) { - if (E->get().value.get_type() != Variant::NIL) { - RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value); - } - } - } else { - RSG::storage->global_variables_instance_free(p_instance->self); - p_instance->instance_allocated_shader_parameters_offset = -1; - } - } - } - - if (p_instance->skeleton.is_valid()) { - RSG::storage->skeleton_update_dependency(p_instance->skeleton, p_instance); - } - - p_instance->clean_up_dependencies(); - } - - _instance_update_list.remove(&p_instance->update_item); - - _update_instance(p_instance); - - p_instance->update_aabb = false; - p_instance->update_dependencies = false; -} - -void RenderingServerScene::update_dirty_instances() { - RSG::storage->update_dirty_resources(); - - while (_instance_update_list.first()) { - _update_dirty_instance(_instance_update_list.first()->self()); - } -} - -bool RenderingServerScene::free(RID p_rid) { - if (camera_owner.owns(p_rid)) { - Camera *camera = camera_owner.getornull(p_rid); - - camera_owner.free(p_rid); - memdelete(camera); - - } else if (scenario_owner.owns(p_rid)) { - Scenario *scenario = scenario_owner.getornull(p_rid); - - while (scenario->instances.first()) { - instance_set_scenario(scenario->instances.first()->self()->self, RID()); - } - RSG::scene_render->free(scenario->reflection_probe_shadow_atlas); - RSG::scene_render->free(scenario->reflection_atlas); - scenario_owner.free(p_rid); - memdelete(scenario); - - } else if (instance_owner.owns(p_rid)) { - // delete the instance - - update_dirty_instances(); - - Instance *instance = instance_owner.getornull(p_rid); - - instance_geometry_set_lightmap(p_rid, RID(), Rect2(), 0); - instance_set_scenario(p_rid, RID()); - instance_set_base(p_rid, RID()); - instance_geometry_set_material_override(p_rid, RID()); - instance_attach_skeleton(p_rid, RID()); - - if (instance->instance_allocated_shader_parameters) { - //free the used shader parameters - RSG::storage->global_variables_instance_free(instance->self); - } - update_dirty_instances(); //in case something changed this - - instance_owner.free(p_rid); - memdelete(instance); - } else { - return false; - } - - return true; -} - -TypedArray<Image> RenderingServerScene::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) { - return RSG::scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size); -} - -RenderingServerScene *RenderingServerScene::singleton = nullptr; - -RenderingServerScene::RenderingServerScene() { - render_pass = 1; - singleton = this; -} - -RenderingServerScene::~RenderingServerScene() { -} diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h deleted file mode 100644 index 646b2a666f..0000000000 --- a/servers/rendering/rendering_server_scene.h +++ /dev/null @@ -1,476 +0,0 @@ -/*************************************************************************/ -/* rendering_server_scene.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 VISUALSERVERSCENE_H -#define VISUALSERVERSCENE_H - -#include "servers/rendering/rasterizer.h" - -#include "core/math/geometry_3d.h" -#include "core/math/octree.h" -#include "core/os/semaphore.h" -#include "core/os/thread.h" -#include "core/templates/local_vector.h" -#include "core/templates/rid_owner.h" -#include "core/templates/self_list.h" -#include "servers/xr/xr_interface.h" - -class RenderingServerScene { -public: - enum { - MAX_INSTANCE_CULL = 65536, - MAX_LIGHTS_CULLED = 4096, - MAX_REFLECTION_PROBES_CULLED = 4096, - MAX_DECALS_CULLED = 4096, - MAX_GI_PROBES_CULLED = 4096, - MAX_ROOM_CULL = 32, - MAX_LIGHTMAPS_CULLED = 4096, - MAX_EXTERIOR_PORTALS = 128, - }; - - uint64_t render_pass; - - static RenderingServerScene *singleton; - - /* CAMERA API */ - - struct Camera { - enum Type { - PERSPECTIVE, - ORTHOGONAL, - FRUSTUM - }; - Type type; - float fov; - float znear, zfar; - float size; - Vector2 offset; - uint32_t visible_layers; - bool vaspect; - RID env; - RID effects; - - Transform transform; - - Camera() { - visible_layers = 0xFFFFFFFF; - fov = 75; - type = PERSPECTIVE; - znear = 0.05; - zfar = 100; - size = 1.0; - offset = Vector2(); - vaspect = false; - } - }; - - mutable RID_PtrOwner<Camera> camera_owner; - - virtual RID camera_create(); - virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far); - virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); - virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far); - virtual void camera_set_transform(RID p_camera, const Transform &p_transform); - virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers); - virtual void camera_set_environment(RID p_camera, RID p_env); - virtual void camera_set_camera_effects(RID p_camera, RID p_fx); - virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable); - - /* SCENARIO API */ - - struct Instance; - - struct Scenario { - RS::ScenarioDebugMode debug; - RID self; - - Octree<Instance, true> octree; - - List<Instance *> directional_lights; - RID environment; - RID fallback_environment; - RID camera_effects; - RID reflection_probe_shadow_atlas; - RID reflection_atlas; - - SelfList<Instance>::List instances; - - LocalVector<RID> dynamic_lights; - - Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; } - }; - - mutable RID_PtrOwner<Scenario> scenario_owner; - - static void *_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int); - static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *); - - virtual RID scenario_create(); - - virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode); - virtual void scenario_set_environment(RID p_scenario, RID p_environment); - virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx); - virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); - virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count); - - /* INSTANCING API */ - - struct InstanceBaseData { - virtual ~InstanceBaseData() {} - }; - - struct Instance : RasterizerScene::InstanceBase { - RID self; - //scenario stuff - OctreeElementID octree_id; - Scenario *scenario; - SelfList<Instance> scenario_item; - - //aabb stuff - bool update_aabb; - bool update_dependencies; - - SelfList<Instance> update_item; - - AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better? - float extra_margin; - ObjectID object_id; - - float lod_begin; - float lod_end; - float lod_begin_hysteresis; - float lod_end_hysteresis; - RID lod_instance; - - Vector<Color> lightmap_target_sh; //target is used for incrementally changing the SH over time, this avoids pops in some corner cases and when going interior <-> exterior - - uint64_t last_render_pass; - uint64_t last_frame_pass; - - uint64_t version; // changes to this, and changes to base increase version - - InstanceBaseData *base_data; - - virtual void dependency_deleted(RID p_dependency) { - if (p_dependency == base) { - singleton->instance_set_base(self, RID()); - } else if (p_dependency == skeleton) { - singleton->instance_attach_skeleton(self, RID()); - } else { - singleton->_instance_queue_update(this, false, true); - } - } - - virtual void dependency_changed(bool p_aabb, bool p_dependencies) { - singleton->_instance_queue_update(this, p_aabb, p_dependencies); - } - - Instance() : - scenario_item(this), - update_item(this) { - octree_id = 0; - scenario = nullptr; - - update_aabb = false; - update_dependencies = false; - - extra_margin = 0; - - visible = true; - - lod_begin = 0; - lod_end = 0; - lod_begin_hysteresis = 0; - lod_end_hysteresis = 0; - - last_render_pass = 0; - last_frame_pass = 0; - version = 1; - base_data = nullptr; - - custom_aabb = nullptr; - } - - ~Instance() { - if (base_data) { - memdelete(base_data); - } - if (custom_aabb) { - memdelete(custom_aabb); - } - } - }; - - SelfList<Instance>::List _instance_update_list; - void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false); - - struct InstanceGeometryData : public InstanceBaseData { - List<Instance *> lighting; - bool lighting_dirty; - bool can_cast_shadows; - bool material_is_animated; - - List<Instance *> decals; - bool decal_dirty; - - List<Instance *> reflection_probes; - bool reflection_dirty; - - List<Instance *> gi_probes; - bool gi_probes_dirty; - - List<Instance *> lightmap_captures; - - InstanceGeometryData() { - lighting_dirty = false; - reflection_dirty = true; - can_cast_shadows = true; - material_is_animated = true; - gi_probes_dirty = true; - decal_dirty = true; - } - }; - - struct InstanceReflectionProbeData : public InstanceBaseData { - Instance *owner; - - struct PairInfo { - List<Instance *>::Element *L; //reflection iterator in geometry - Instance *geometry; - }; - List<PairInfo> geometries; - - RID instance; - bool reflection_dirty; - SelfList<InstanceReflectionProbeData> update_list; - - int render_step; - - InstanceReflectionProbeData() : - update_list(this) { - reflection_dirty = true; - render_step = -1; - } - }; - - struct InstanceDecalData : public InstanceBaseData { - Instance *owner; - RID instance; - - struct PairInfo { - List<Instance *>::Element *L; //reflection iterator in geometry - Instance *geometry; - }; - List<PairInfo> geometries; - - InstanceDecalData() { - } - }; - - SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list; - - struct InstanceLightData : public InstanceBaseData { - struct PairInfo { - List<Instance *>::Element *L; //light iterator in geometry - Instance *geometry; - }; - - RID instance; - uint64_t last_version; - List<Instance *>::Element *D; // directional light in scenario - - bool shadow_dirty; - - List<PairInfo> geometries; - - Instance *baked_light; - - RS::LightBakeMode bake_mode; - uint32_t max_sdfgi_cascade = 2; - - uint64_t sdfgi_cascade_light_pass = 0; - - InstanceLightData() { - bake_mode = RS::LIGHT_BAKE_DISABLED; - shadow_dirty = true; - D = nullptr; - last_version = 0; - baked_light = nullptr; - } - }; - - struct InstanceGIProbeData : public InstanceBaseData { - Instance *owner; - - struct PairInfo { - List<Instance *>::Element *L; //gi probe iterator in geometry - Instance *geometry; - }; - - List<PairInfo> geometries; - List<PairInfo> dynamic_geometries; - - Set<Instance *> lights; - - struct LightCache { - RS::LightType type; - Transform transform; - Color color; - float energy; - float bake_energy; - float radius; - float attenuation; - float spot_angle; - float spot_attenuation; - bool has_shadow; - }; - - Vector<LightCache> light_cache; - Vector<RID> light_instances; - - RID probe_instance; - - bool invalid; - uint32_t base_version; - - SelfList<InstanceGIProbeData> update_element; - - InstanceGIProbeData() : - update_element(this) { - invalid = true; - base_version = 0; - } - }; - - SelfList<InstanceGIProbeData>::List gi_probe_update_list; - - struct InstanceLightmapData : public InstanceBaseData { - struct PairInfo { - List<Instance *>::Element *L; //iterator in geometry - Instance *geometry; - }; - List<PairInfo> geometries; - - Set<Instance *> users; - - InstanceLightmapData() { - } - }; - - Set<Instance *> heightfield_particle_colliders_update_list; - - int instance_cull_count; - Instance *instance_cull_result[MAX_INSTANCE_CULL]; - Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps - Instance *light_cull_result[MAX_LIGHTS_CULLED]; - RID sdfgi_light_cull_result[MAX_LIGHTS_CULLED]; - RID light_instance_cull_result[MAX_LIGHTS_CULLED]; - uint64_t sdfgi_light_cull_pass = 0; - int light_cull_count; - int directional_light_count; - RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED]; - RID decal_instance_cull_result[MAX_DECALS_CULLED]; - int reflection_probe_cull_count; - int decal_cull_count; - RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED]; - int gi_probe_cull_count; - Instance *lightmap_cull_result[MAX_LIGHTS_CULLED]; - int lightmap_cull_count; - - RID_PtrOwner<Instance> instance_owner; - - virtual RID instance_create(); - - virtual void instance_set_base(RID p_instance, RID p_base); - virtual void instance_set_scenario(RID p_instance, RID p_scenario); - virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); - virtual void instance_set_transform(RID p_instance, const Transform &p_transform); - virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); - virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); - virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material); - virtual void instance_set_visible(RID p_instance, bool p_visible); - - virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb); - - virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton); - virtual void instance_set_exterior(RID p_instance, bool p_enabled); - - virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin); - - // don't use these in a game! - virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const; - virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; - virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const; - - virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled); - virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting); - virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); - - virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin); - virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance); - virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index); - - void _update_instance_shader_parameters_from_material(Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RasterizerScene::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material); - - virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value); - virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const; - virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const; - virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const; - - _FORCE_INLINE_ void _update_instance(Instance *p_instance); - _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); - _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance); - _FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance); - - _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario); - - RID _render_get_environment(RID p_camera, RID p_scenario); - - bool _render_reflection_probe_step(Instance *p_instance, int p_step); - void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true); - void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass); - void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas); - - void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); - void render_camera(RID p_render_buffers, Ref<XRInterface> &p_interface, XRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); - void update_dirty_instances(); - - void render_particle_colliders(); - void render_probes(); - - TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size); - - bool free(RID p_rid); - - RenderingServerScene(); - virtual ~RenderingServerScene(); -}; - -#endif // VISUALSERVERSCENE_H diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp index 40ad228fd0..3572c4dc78 100644 --- a/servers/rendering/rendering_server_wrap_mt.cpp +++ b/servers/rendering/rendering_server_wrap_mt.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index d33bdb043a..3db90c32df 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -129,6 +129,8 @@ public: FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &) FUNC2RC(Variant, shader_get_param_default, RID, const StringName &) + FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID) + /* COMMON MATERIAL API */ FUNCRID(material) @@ -143,10 +145,12 @@ public: /* MESH API */ - virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces) { - return rendering_server->mesh_create_from_surfaces(p_surfaces); + virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) { + return rendering_server->mesh_create_from_surfaces(p_surfaces, p_blend_shape_count); } + FUNC2(mesh_set_blend_shape_count, RID, int) + FUNCRID(mesh) FUNC2(mesh_add_surface, RID, const SurfaceData &) @@ -244,6 +248,7 @@ public: FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) FUNC2(light_directional_set_blend_splits, RID, bool) + FUNC2(light_directional_set_sky_only, RID, bool) FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) /* PROBE API */ @@ -263,6 +268,7 @@ public: FUNC2(reflection_probe_set_enable_shadows, RID, bool) FUNC2(reflection_probe_set_cull_mask, RID, uint32_t) FUNC2(reflection_probe_set_resolution, RID, int) + FUNC2(reflection_probe_set_lod_threshold, RID, float) /* DECAL API */ @@ -447,6 +453,8 @@ public: FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) FUNC2(viewport_set_use_debanding, RID, bool) + FUNC2(viewport_set_lod_threshold, RID, float) + //this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) { return rendering_server->viewport_get_render_info(p_viewport, p_info); @@ -492,9 +500,9 @@ public: FUNC6(environment_set_ssr, RID, bool, int, float, float, float) FUNC1(environment_set_ssr_roughness_quality, EnvironmentSSRRoughnessQuality) - FUNC9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) + FUNC10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float) - FUNC2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) + FUNC6(environment_set_ssao_quality, EnvironmentSSAOQuality, bool, float, int, float, float) FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float) FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount) @@ -506,7 +514,7 @@ public: FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) - FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID) + FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) @@ -572,6 +580,7 @@ public: FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float) FUNC2(instance_geometry_set_as_instance_lod, RID, RID) FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int) + FUNC2(instance_geometry_set_lod_bias, RID, float) FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &) FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &) @@ -618,7 +627,7 @@ public: FUNC2(canvas_item_set_draw_behind_parent, RID, bool) FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) - FUNC4(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float) + FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float) FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) @@ -769,6 +778,10 @@ public: return rendering_server->get_frame_profile(); } + virtual float get_frame_setup_time_cpu() const { + return rendering_server->get_frame_setup_time_cpu(); + } + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { rendering_server->sdfgi_set_debug_probe_select(p_position, p_dir); } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 1ab353c9d0..2fa3355d2f 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -223,7 +223,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { String ShaderLanguage::get_token_text(Token p_token) { String name = token_names[p_token.type]; - if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_REAL_CONSTANT) { + if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_FLOAT_CONSTANT) { name += "(" + rtos(p_token.constant) + ")"; } else if (p_token.type == TK_IDENTIFIER) { name += "(" + String(p_token.text) + ")"; @@ -637,7 +637,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { char_idx += str.length(); Token tk; if (period_found || exponent_found || float_suffix_found) { - tk.type = TK_REAL_CONSTANT; + tk.type = TK_FLOAT_CONSTANT; } else { tk.type = TK_INT_CONSTANT; } @@ -913,6 +913,7 @@ void ShaderLanguage::clear() { char_idx = 0; error_set = false; error_str = ""; + last_const = false; while (nodes) { Node *n = nodes; nodes = nodes->next; @@ -920,7 +921,7 @@ void ShaderLanguage::clear() { } } -bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) { +bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) { if (p_function_info.built_ins.has(p_identifier)) { if (r_data_type) { *r_data_type = p_function_info.built_ins[p_identifier].type; @@ -968,6 +969,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea if (r_struct_name) { *r_struct_name = p_block->variables[p_identifier].struct_name; } + if (r_constant_value) { + *r_constant_value = p_block->variables[p_identifier].value; + } return true; } @@ -1028,6 +1032,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea } if (shader->constants.has(p_identifier)) { + if (r_is_const) { + *r_is_const = true; + } if (r_data_type) { *r_data_type = shader->constants[p_identifier].type; } @@ -1040,6 +1047,11 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea if (r_struct_name) { *r_struct_name = shader->constants[p_identifier].type_str; } + if (r_constant_value) { + if (shader->constants[p_identifier].initializer && shader->constants[p_identifier].initializer->values.size() == 1) { + *r_constant_value = shader->constants[p_identifier].initializer->values[0]; + } + } return true; } @@ -3174,7 +3186,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi } bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) { - for (int i = 0; shader->functions.size(); i++) { + for (int i = 0; i < shader->functions.size(); i++) { if (shader->functions[i].name == p_name) { ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false); FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument]; @@ -3208,7 +3220,7 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringNam } bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin) { - for (int i = 0; shader->functions.size(); i++) { + for (int i = 0; i < shader->functions.size(); i++) { if (shader->functions[i].name == p_name) { ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false); FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument]; @@ -3241,6 +3253,137 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa ERR_FAIL_V(false); //bug? function not found } +ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size) { + DataType type = TYPE_VOID; + String struct_name = ""; + int array_size = 0; + bool auto_size = false; + Token tk = _get_token(); + + if (tk.type == TK_CURLY_BRACKET_OPEN) { + auto_size = true; + } else { + if (shader->structs.has(tk.text)) { + type = TYPE_STRUCT; + struct_name = tk.text; + } else { + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for array"); + return nullptr; + } + type = get_token_datatype(tk.type); + } + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + TkPos pos = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + array_size = p_array_size; + tk = _get_token(); + } else { + _set_tkpos(pos); + + Node *n = _parse_and_reduce_expression(p_block, p_function_info); + if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { + _set_error("Expected single integer constant > 0"); + return nullptr; + } + + ConstantNode *cnode = (ConstantNode *)n; + if (cnode->values.size() == 1) { + array_size = cnode->values[0].sint; + if (array_size <= 0) { + _set_error("Expected single integer constant > 0"); + return nullptr; + } + } else { + _set_error("Expected single integer constant > 0"); + return nullptr; + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return nullptr; + } else { + tk = _get_token(); + } + } + } else { + _set_error("Expected '['"); + return nullptr; + } + + if (type != p_type || struct_name != p_struct_name || array_size != p_array_size) { + String error_str = "Cannot convert from '"; + if (type == TYPE_STRUCT) { + error_str += struct_name; + } else { + error_str += get_datatype_name(type); + } + error_str += "["; + error_str += itos(array_size); + error_str += "]'"; + error_str += " to '"; + if (type == TYPE_STRUCT) { + error_str += p_struct_name; + } else { + error_str += get_datatype_name(p_type); + } + error_str += "["; + error_str += itos(p_array_size); + error_str += "]'"; + _set_error(error_str); + return nullptr; + } + } + + ArrayConstructNode *an = alloc_node<ArrayConstructNode>(); + an->datatype = p_type; + an->struct_name = p_struct_name; + + if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization + while (true) { + Node *n = _parse_and_reduce_expression(p_block, p_function_info); + if (!n) { + return nullptr; + } + + if (p_type != n->get_datatype() || p_struct_name != n->get_datatype_name()) { + _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'"); + return nullptr; + } + + tk = _get_token(); + if (tk.type == TK_COMMA) { + an->initializer.push_back(n); + } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) { + an->initializer.push_back(n); + break; + } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) { + an->initializer.push_back(n); + break; + } else { + if (auto_size) { + _set_error("Expected '}' or ','"); + } else { + _set_error("Expected ')' or ','"); + } + return nullptr; + } + } + if (an->initializer.size() != p_array_size) { + _set_error("Array size mismatch"); + return nullptr; + } + } else { + _set_error("Expected array initialization!"); + return nullptr; + } + + return an; +} + ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info) { Vector<Expression> expression; @@ -3269,7 +3412,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } - } else if (tk.type == TK_REAL_CONSTANT) { + } else if (tk.type == TK_FLOAT_CONSTANT) { ConstantNode *constant = alloc_node<ConstantNode>(); ConstantNode::Value v; v.real = tk.constant; @@ -3384,142 +3527,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons Node *nexpr; if (pstruct->members[i]->array_size != 0) { - DataType type = pstruct->members[i]->get_datatype(); - String struct_name = pstruct->members[i]->struct_name; - int array_size = pstruct->members[i]->array_size; - - DataType type2; - String struct_name2 = ""; - int array_size2 = 0; - - bool auto_size = false; - - tk = _get_token(); - - if (tk.type == TK_CURLY_BRACKET_OPEN) { - auto_size = true; - } else { - if (shader->structs.has(tk.text)) { - type2 = TYPE_STRUCT; - struct_name2 = tk.text; - } else { - if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for array"); - return nullptr; - } - type2 = get_token_datatype(tk.type); - } - - tk = _get_token(); - if (tk.type == TK_BRACKET_OPEN) { - TkPos pos2 = _get_tkpos(); - tk = _get_token(); - if (tk.type == TK_BRACKET_CLOSE) { - array_size2 = array_size; - tk = _get_token(); - } else { - _set_tkpos(pos2); - - Node *n = _parse_and_reduce_expression(p_block, p_function_info); - if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { - _set_error("Expected single integer constant > 0"); - return nullptr; - } - - ConstantNode *cnode = (ConstantNode *)n; - if (cnode->values.size() == 1) { - array_size2 = cnode->values[0].sint; - if (array_size2 <= 0) { - _set_error("Expected single integer constant > 0"); - return nullptr; - } - } else { - _set_error("Expected single integer constant > 0"); - return nullptr; - } - - tk = _get_token(); - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); - return nullptr; - } else { - tk = _get_token(); - } - } - } else { - _set_error("Expected '['"); - return nullptr; - } - - if (type != type2 || struct_name != struct_name2 || array_size != array_size2) { - String error_str = "Cannot convert from '"; - if (type2 == TYPE_STRUCT) { - error_str += struct_name2; - } else { - error_str += get_datatype_name(type2); - } - error_str += "["; - error_str += itos(array_size2); - error_str += "]'"; - error_str += " to '"; - if (type == TYPE_STRUCT) { - error_str += struct_name; - } else { - error_str += get_datatype_name(type); - } - error_str += "["; - error_str += itos(array_size); - error_str += "]'"; - _set_error(error_str); - return nullptr; - } - } - - ArrayConstructNode *an = alloc_node<ArrayConstructNode>(); - an->datatype = type; - an->struct_name = struct_name; - - if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization - while (true) { - Node *n = _parse_and_reduce_expression(p_block, p_function_info); - if (!n) { - return nullptr; - } - - if (type != n->get_datatype() || struct_name != n->get_datatype_name()) { - _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'"); - return nullptr; - } - - tk = _get_token(); - if (tk.type == TK_COMMA) { - an->initializer.push_back(n); - continue; - } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) { - an->initializer.push_back(n); - break; - } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) { - an->initializer.push_back(n); - break; - } else { - if (auto_size) { - _set_error("Expected '}' or ','"); - } else { - _set_error("Expected ')' or ','"); - } - return nullptr; - } - } - if (an->initializer.size() != array_size) { - _set_error("Array size mismatch"); - return nullptr; - } - } else { - _set_error("Expected array initialization!"); + nexpr = _parse_array_constructor(p_block, p_function_info, pstruct->members[i]->get_datatype(), pstruct->members[i]->struct_name, pstruct->members[i]->array_size); + if (!nexpr) { return nullptr; } - - nexpr = an; } else { nexpr = _parse_and_reduce_expression(p_block, p_function_info); if (!nexpr) { @@ -3722,6 +3733,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else { //an identifier + last_const = false; _set_tkpos(pos); DataType data_type; @@ -3749,6 +3761,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Unknown identifier in expression: " + String(identifier)); return nullptr; } + last_const = is_const; if (ident_type == IDENTIFIER_FUNCTION) { _set_error("Can't use function as identifier: " + String(identifier)); @@ -3758,16 +3771,30 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons Node *index_expression = nullptr; Node *call_expression = nullptr; + Node *assign_expression = nullptr; if (array_size > 0) { tk = _get_token(); - if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD) { - _set_error("Expected '[' or '.'"); + if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) { + _set_error("Expected '[','.' or '='"); return nullptr; } - if (tk.type == TK_PERIOD) { + if (tk.type == TK_OP_ASSIGN) { + if (is_const) { + _set_error("Constants cannot be modified."); + return nullptr; + } + if (shader->varyings.has(identifier) && current_function != String("vertex")) { + _set_error("Varyings can only be assigned in vertex function."); + return nullptr; + } + assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size); + if (!assign_expression) { + return nullptr; + } + } else if (tk.type == TK_PERIOD) { completion_class = TAG_ARRAY; p_block->block_tag = SubClassTag::TAG_ARRAY; call_expression = _parse_and_reduce_expression(p_block, p_function_info); @@ -3791,7 +3818,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (index_expression->type == Node::TYPE_CONSTANT) { ConstantNode *cnode = (ConstantNode *)index_expression; if (cnode) { - if (!cnode->values.empty()) { + if (!cnode->values.is_empty()) { int value = cnode->values[0].sint; if (value < 0 || value >= array_size) { _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); @@ -3814,6 +3841,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons arrname->struct_name = struct_name; arrname->index_expression = index_expression; arrname->call_expression = call_expression; + arrname->assign_expression = assign_expression; arrname->is_const = is_const; expr = arrname; @@ -4154,7 +4182,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (array_size > 0) { tk = _get_token(); - if (tk.type == TK_PERIOD) { + if (tk.type == TK_OP_ASSIGN) { + if (last_const) { + last_const = false; + _set_error("Constants cannot be modified."); + return nullptr; + } + Node *assign_expression = _parse_array_constructor(p_block, p_function_info, member_type, member_struct_name, array_size); + if (!assign_expression) { + return nullptr; + } + mn->assign_expression = assign_expression; + } else if (tk.type == TK_PERIOD) { _set_error("Nested array length() is not yet implemented"); return nullptr; } else if (tk.type == TK_BRACKET_OPEN) { @@ -4171,7 +4210,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (index_expression->type == Node::TYPE_CONSTANT) { ConstantNode *cnode = (ConstantNode *)index_expression; if (cnode) { - if (!cnode->values.empty()) { + if (!cnode->values.is_empty()) { int value = cnode->values[0].sint; if (value < 0 || value >= array_size) { _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); @@ -4189,7 +4228,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons mn->index_expression = index_expression; } else { - _set_error("Expected '[' or '.'"); + _set_error("Expected '[','.' or '='"); return nullptr; } } @@ -5010,17 +5049,53 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun decl.name = name; decl.size = 0U; + pos = _get_tkpos(); tk = _get_token(); if (tk.type == TK_BRACKET_CLOSE) { unknown_size = true; } else { if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { + _set_tkpos(pos); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); + if (n) { + if (n->type == Node::TYPE_VARIABLE) { + VariableNode *vn = static_cast<VariableNode *>(n); + if (vn) { + ConstantNode::Value v; + DataType data_type; + + _find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v); + + if (is_const) { + if (data_type == TYPE_INT) { + int32_t value = v.sint; + if (value > 0) { + node->size_expression = n; + decl.size = (uint32_t)value; + } + } else if (data_type == TYPE_UINT) { + uint32_t value = v.uint; + if (value > 0U) { + node->size_expression = n; + decl.size = value; + } + } + } + } + } else if (n->type == Node::TYPE_OPERATOR) { + _set_error("Array size expressions are not yet implemented."); + return ERR_PARSE_ERROR; + } + } + } else if (((int)tk.constant) > 0) { + decl.size = (uint32_t)tk.constant; + } + + if (decl.size == 0U) { _set_error("Expected integer constant > 0 or ']'"); return ERR_PARSE_ERROR; } - - decl.size = ((uint32_t)tk.constant); tk = _get_token(); if (tk.type != TK_BRACKET_CLOSE) { @@ -5218,7 +5293,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun _set_error("Expected array initialization"); return ERR_PARSE_ERROR; } - if (is_const) { + if (node->is_const) { _set_error("Expected initialization of constant"); return ERR_PARSE_ERROR; } @@ -5252,6 +5327,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } decl.initializer = n; + if (n->type == Node::TYPE_CONSTANT) { + ConstantNode *const_node = static_cast<ConstantNode *>(n); + if (const_node && const_node->values.size() == 1) { + var.value = const_node->values[0]; + } + } + if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) { _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'"); return ERR_PARSE_ERROR; @@ -5420,18 +5502,29 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i]; if (flow) { if (flow->flow_op == FLOW_OP_CASE) { - ConstantNode *n2 = static_cast<ConstantNode *>(flow->expressions[0]); - if (!n2) { - return ERR_PARSE_ERROR; - } - if (n2->values.empty()) { - return ERR_PARSE_ERROR; - } - if (constants.has(n2->values[0].sint)) { - _set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'"); - return ERR_PARSE_ERROR; + if (flow->expressions[0]->type == Node::TYPE_CONSTANT) { + ConstantNode *cn = static_cast<ConstantNode *>(flow->expressions[0]); + if (!cn || cn->values.is_empty()) { + return ERR_PARSE_ERROR; + } + if (constants.has(cn->values[0].sint)) { + _set_error("Duplicated case label: '" + itos(cn->values[0].sint) + "'"); + return ERR_PARSE_ERROR; + } + constants.insert(cn->values[0].sint); + } else if (flow->expressions[0]->type == Node::TYPE_VARIABLE) { + VariableNode *vn = static_cast<VariableNode *>(flow->expressions[0]); + if (!vn) { + return ERR_PARSE_ERROR; + } + ConstantNode::Value v; + _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, nullptr, nullptr, nullptr, &v); + if (constants.has(v.sint)) { + _set_error("Duplicated case label: '" + itos(v.sint) + "'"); + return ERR_PARSE_ERROR; + } + constants.insert(v.sint); } - constants.insert(n2->values[0].sint); } else if (flow->flow_op == FLOW_OP_DEFAULT) { continue; } else { @@ -5467,12 +5560,38 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun tk = _get_token(); } + Node *n = nullptr; + if (tk.type != TK_INT_CONSTANT) { - _set_error("Expected integer constant"); - return ERR_PARSE_ERROR; - } + bool correct_constant_expression = false; + DataType data_type; - int constant = (int)tk.constant * sign; + if (tk.type == TK_IDENTIFIER) { + bool is_const; + _find_identifier(p_block, false, p_function_info, tk.text, &data_type, nullptr, &is_const); + if (is_const) { + if (data_type == TYPE_INT) { + correct_constant_expression = true; + } + } + } + if (!correct_constant_expression) { + _set_error("Expected integer constant"); + return ERR_PARSE_ERROR; + } + + VariableNode *vn = alloc_node<VariableNode>(); + vn->name = tk.text; + n = vn; + } else { + ConstantNode::Value v; + v.sint = (int)tk.constant * sign; + + ConstantNode *cn = alloc_node<ConstantNode>(); + cn->values.push_back(v); + cn->datatype = TYPE_INT; + n = cn; + } tk = _get_token(); @@ -5484,12 +5603,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun ControlFlowNode *cf = alloc_node<ControlFlowNode>(); cf->flow_op = FLOW_OP_CASE; - ConstantNode *n = alloc_node<ConstantNode>(); - ConstantNode::Value v; - v.sint = constant; - n->values.push_back(v); - n->datatype = TYPE_INT; - BlockNode *case_block = alloc_node<BlockNode>(); case_block->block_type = BlockNode::BLOCK_TYPE_CASE; case_block->parent_block = p_block; @@ -6192,7 +6305,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } uniform2.texture_order = -1; - uniform2.order = uniforms++; + if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) { + uniform2.order = uniforms++; + } } uniform2.type = type; uniform2.scope = uniform_scope; @@ -6260,7 +6375,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } - if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { + if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) { _set_error("Expected integer constant"); return ERR_PARSE_ERROR; } @@ -6284,7 +6399,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } - if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { + if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) { _set_error("Expected integer constant after ','"); return ERR_PARSE_ERROR; } @@ -6297,7 +6412,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_COMMA) { tk = _get_token(); - if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { + if (tk.type != TK_FLOAT_CONSTANT && tk.type != TK_INT_CONSTANT) { _set_error("Expected integer constant after ','"); return ERR_PARSE_ERROR; } diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 3a9f408dc0..27767378f9 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -46,7 +46,7 @@ public: TK_IDENTIFIER, TK_TRUE, TK_FALSE, - TK_REAL_CONSTANT, + TK_FLOAT_CONSTANT, TK_INT_CONSTANT, TK_TYPE_VOID, TK_TYPE_BOOL, @@ -414,6 +414,7 @@ public: StringName name; Node *index_expression = nullptr; Node *call_expression = nullptr; + Node *assign_expression = nullptr; bool is_const = false; virtual DataType get_datatype() const { return datatype_cache; } @@ -437,6 +438,7 @@ public: DataType datatype = TYPE_VOID; String struct_name; bool is_const = false; + Node *size_expression = nullptr; struct Declaration { StringName name; @@ -496,6 +498,7 @@ public: int line; //for completion int array_size; bool is_const; + ConstantNode::Value value; }; Map<StringName, Variable> variables; @@ -519,13 +522,14 @@ public: DataType basetype = TYPE_VOID; bool basetype_const = false; StringName base_struct_name; - DataPrecision precision; + DataPrecision precision = PRECISION_DEFAULT; DataType datatype = TYPE_VOID; int array_size = 0; StringName struct_name; StringName name; Node *owner = nullptr; Node *index_expression = nullptr; + Node *assign_expression = nullptr; bool has_swizzling_duplicates = false; virtual DataType get_datatype() const { return datatype; } @@ -774,6 +778,7 @@ private: int tk_line; StringName current_function; + bool last_const = false; struct TkPos { int char_idx; @@ -819,7 +824,7 @@ private: IDENTIFIER_CONSTANT, }; - bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr); + bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr, ConstantNode::Value *r_constant_value = nullptr); bool _is_operator_assign(Operator p_op) const; bool _validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message = nullptr); bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr); @@ -861,6 +866,7 @@ private: bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin); Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info); + Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size); ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); Node *_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index bd61f2a549..e99b8504bb 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ @@ -67,6 +67,12 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BONE_INDICES"] = ShaderLanguage::TYPE_UVEC4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BONE_WEIGHTS"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM0"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM1"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM2"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM3"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].can_discard = false; //builtins @@ -88,8 +94,8 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_MAP"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_MAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); @@ -236,8 +242,8 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["LIGHT_VERTEX"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; - shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_MAP"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_MAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); @@ -341,7 +347,7 @@ ShaderTypes::ShaderTypes() { emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("custom", ShaderLanguage::TYPE_VEC4)); emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("flags", ShaderLanguage::TYPE_UINT)); emit_vertex_func.return_type = ShaderLanguage::TYPE_BOOL; //whether it could emit - shader_modes[RS::SHADER_PARTICLES].functions["compute"].stage_functions["emit_particle"] = emit_vertex_func; + shader_modes[RS::SHADER_PARTICLES].functions["compute"].stage_functions["emit_subparticle"] = emit_vertex_func; } shader_modes[RS::SHADER_PARTICLES].modes.push_back("collision_use_scale"); diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h index 50f910babb..e59cef6b79 100644 --- a/servers/rendering/shader_types.h +++ b/servers/rendering/shader_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 */ |